diff --git a/.gitattributes b/.gitattributes index 0a56ba75f93..5a817c30b6d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,4 +6,5 @@ ThirdPartyNotices.txt eol=crlf *.bat eol=crlf *.cmd eol=crlf *.ps1 eol=lf -*.sh eol=lf \ No newline at end of file +*.sh eol=lf +*.rtf -text \ No newline at end of file diff --git a/.github/classifier.yml b/.github/classifier.yml index e0f0cec8169..8acb0002347 100644 --- a/.github/classifier.yml +++ b/.github/classifier.yml @@ -15,44 +15,131 @@ css-less-scss: [], debug-console: [], debug: { - assignees: [ isidorn ], + assignees: [ weinand ], assignLabel: false }, - diff-editor: [], - dropdown: [], - editor: { + diff-editor: : { assignees: [], assignLabel: false }, - editor-1000-limit: [], - editor-autoclosing: [], - editor-autoindent: [], - editor-brackets: [], - editor-clipboard: [], - editor-code-actions: [], - editor-code-lens: [], - editor-color-picker: [], - editor-colors: [], - editor-columnselect: [], - editor-commands: [], - editor-contrib: [], - editor-drag-and-drop: [], - editor-find: [], - editor-folding: [], - editor-hover: [], - editor-ime: [], - editor-input: [], - editor-ligatures: [], - editor-links: [], - editor-minimap: [], - editor-multicursor: [], - editor-parameter-hints: [], - editor-rendering: [], - editor-smooth: [], - editor-symbols: [], - editor-textbuffer: [], - editor-wrapping: [], - emmet: [ octref, ramya-rao-a ], + dropdown: [], + editor: : { + assignees: [], + assignLabel: false + }, + editor-1000-limit: : { + assignees: [], + assignLabel: false + }, + editor-autoclosing: : { + assignees: [], + assignLabel: false + }, + editor-autoindent: : { + assignees: [], + assignLabel: false + }, + editor-brackets: : { + assignees: [], + assignLabel: false + }, + editor-clipboard: : { + assignees: [], + assignLabel: false + }, + editor-code-actions: : { + assignees: [], + assignLabel: false + }, + editor-code-lens: : { + assignees: [], + assignLabel: false + }, + editor-color-picker: : { + assignees: [], + assignLabel: false + }, + editor-colors: : { + assignees: [], + assignLabel: false + }, + editor-columnselect: : { + assignees: [], + assignLabel: false + }, + editor-commands: : { + assignees: [], + assignLabel: false + }, + editor-contrib: : { + assignees: [], + assignLabel: false + }, + editor-drag-and-drop: : { + assignees: [], + assignLabel: false + }, + editor-find: : { + assignees: [], + assignLabel: false + }, + editor-folding: : { + assignees: [], + assignLabel: false + }, + editor-hover: : { + assignees: [], + assignLabel: false + }, + editor-ime: : { + assignees: [], + assignLabel: false + }, + editor-input: : { + assignees: [], + assignLabel: false + }, + editor-ligatures: : { + assignees: [], + assignLabel: false + }, + editor-links: : { + assignees: [], + assignLabel: false + }, + editor-minimap: : { + assignees: [], + assignLabel: false + }, + editor-multicursor: : { + assignees: [], + assignLabel: false + }, + editor-parameter-hints: : { + assignees: [], + assignLabel: false + }, + editor-rendering: : { + assignees: [], + assignLabel: false + }, + editor-smooth: : { + assignees: [], + assignLabel: false + }, + editor-symbols: : { + assignees: [], + assignLabel: false + }, + editor-textbuffer: : { + assignees: [], + assignLabel: false + }, + editor-wrapping: : { + assignees: [], + assignLabel: false + }, + emmet: [ octref ], error-list: [], explorer-custom: [], extension-host: [], @@ -81,14 +168,20 @@ hot-exit: [], html: [], install-update: [], - integrated-terminal: [ Tyriar ], + integrated-terminal: [], integration-test: [], intellisense-config: [], issue-reporter: [ RMacfarlane ], javascript: [ mjbvz ], json: [], - keyboard-layout: [], - keybindings: [], + keyboard-layout: : { + assignees: [], + assignLabel: false + }, + keybindings: : { + assignees: [], + assignLabel: false + }, keybindings-editor: [], lang-diagnostics: [], languages basic: [], diff --git a/.github/commands.yml b/.github/commands.yml index 70d41295408..c9279232529 100644 --- a/.github/commands.yml +++ b/.github/commands.yml @@ -51,6 +51,12 @@ action: 'close', comment: "The described behavior is how it is expected to work. If you disagree, please explain what is expected and what is not in more detail. See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!" }, + { + type: 'label', + name: '*english-please', + action: 'close', + comment: "This issue is being closed because its description is not in English, that makes it hard for us to work on it. Please open a new issue with an English description. You might find [Bing Translator](https://www.bing.com/translator) useful." + }, { type: 'comment', name: 'duplicate', @@ -99,7 +105,7 @@ { type: 'comment', name: 'a11ymas', - allowUsers: ['AccessibilityTestingTeam-TCS'], + allowUsers: ['AccessibilityTestingTeam-TCS', 'dixitsonali95', 'Mohini78', 'ChitrarupaSharma', 'mspatil110', 'umasarath52', 'v-umnaik'], action: 'updateLabels', addLabel: 'a11ymas' }, diff --git a/.gitignore b/.gitignore index 6a9804cd237..160c42ed74b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store +.cache npm-debug.log Thumbs.db node_modules/ @@ -14,6 +15,16 @@ out-editor-min/ out-monaco-editor-core/ out-vscode/ out-vscode-min/ +out-vscode-reh/ +out-vscode-reh-min/ +out-vscode-reh-pkg/ +out-vscode-reh-web/ +out-vscode-reh-web-min/ +out-vscode-reh-web-pkg/ +out-vscode-web/ +out-vscode-web-min/ +src/vs/server +resources/server build/node_modules coverage/ test_data/ diff --git a/.nvmrc b/.nvmrc index 32c861f970d..f599e28b8ab 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -8.9.2 +10 diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 55cfea092a6..b4336e7d127 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -4,6 +4,7 @@ "recommendations": [ "ms-vscode.vscode-typescript-tslint-plugin", "dbaeumer.vscode-eslint", + "EditorConfig.EditorConfig", "msjsdiag.debugger-for-chrome" ] } diff --git a/.vscode/launch.json b/.vscode/launch.json index e217c585b42..1d8207865fd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -123,7 +123,8 @@ "request": "launch", "name": "Launch VS Code", "windows": { - "runtimeExecutable": "${workspaceFolder}/scripts/code.bat" + "runtimeExecutable": "${workspaceFolder}/scripts/code.bat", + "timeout": 20000 }, "osx": { "runtimeExecutable": "${workspaceFolder}/scripts/code.sh" @@ -131,6 +132,9 @@ "linux": { "runtimeExecutable": "${workspaceFolder}/scripts/code.sh" }, + "env": { + "VSCODE_EXTHOST_WILL_SEND_SOCKET": null + }, "breakOnLoad": false, "urlFilter": "*workbench.html*", "runtimeArgs": [ @@ -144,6 +148,9 @@ "request": "launch", "name": "Launch VS Code (Main Process)", "runtimeExecutable": "${workspaceFolder}/scripts/code.sh", + "windows": { + "runtimeExecutable": "${workspaceFolder}/scripts/code.bat", + }, "runtimeArgs": [ "--no-cached-data" ], @@ -193,8 +200,8 @@ { "type": "node", "request": "launch", - "name": "Unit Tests", - "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "name": "Run Unit Tests", + "program": "${workspaceFolder}/test/electron/index.js", "runtimeExecutable": "${workspaceFolder}/.build/electron/Code - OSS.app/Contents/MacOS/Electron", "windows": { "runtimeExecutable": "${workspaceFolder}/.build/electron/Code - OSS.exe" @@ -204,14 +211,9 @@ }, "outputCapture": "std", "args": [ - "--delay", - "--timeout", - "2000" + "--remote-debugging-port=9222" ], "cwd": "${workspaceFolder}", - "env": { - "ELECTRON_RUN_AS_NODE": "true" - }, "outFiles": [ "${workspaceFolder}/out/**/*.js" ] @@ -268,6 +270,13 @@ "Launch VS Code", "Attach to Extension Host" ] - } + }, + { + "name": "Debug Unit Tests", + "configurations": [ + "Attach to VS Code", + "Run Unit Tests" + ] + }, ] -} +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 8b9ca6cd07b..1a760bdda6b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -42,11 +42,23 @@ "emmet.excludeLanguages": [], "typescript.preferences.importModuleSpecifier": "non-relative", "typescript.preferences.quoteStyle": "single", - "json.schemas": [{ - "fileMatch": [ "cgmanifest.json" ], - "url": "./.vscode/cgmanifest.schema.json" - }, { - "fileMatch": [ "cglicenses.json" ], - "url": "./.vscode/cglicenses.schema.json" - }] -} + "json.schemas": [ + { + "fileMatch": [ + "cgmanifest.json" + ], + "url": "./.vscode/cgmanifest.schema.json" + }, + { + "fileMatch": [ + "cglicenses.json" + ], + "url": "./.vscode/cglicenses.schema.json" + } + ], + "git.ignoreLimitWarning": true, + "remote.extensionKind": { + "msjsdiag.debugger-for-chrome": "workspace" + }, + "files.insertFinalNewline": true +} \ No newline at end of file diff --git a/.vscode/shared.code-snippets b/.vscode/shared.code-snippets index 6d6690a0282..fb3df23dd42 100644 --- a/.vscode/shared.code-snippets +++ b/.vscode/shared.code-snippets @@ -23,11 +23,13 @@ "description": "Insert Copyright Statement" }, "TS -> Inject Service": { + "scope": "typescript", "description": "Constructor Injection Pattern", "prefix": "@inject", "body": "@$1 private readonly _$2: ${1},$0" }, "TS -> Event & Emitter": { + "scope": "typescript", "prefix": "emitter", "description": "Add emitter and event properties", "body": [ diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 4a704226c46..5db8fb3fbc5 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -30,19 +30,16 @@ }, { "type": "npm", - "script": "strict-null-check-watch", - "label": "TS - Strict Null Checks", + "script": "strict-initialization-watch", + "label": "TS - Strict Initialization", "isBackground": true, "presentation": { "reveal": "never" }, "problemMatcher": { "base": "$tsc-watch", - "owner": "typescript-strict-null", + "owner": "typescript-strict-initialization", "applyTo": "allDocuments" - }, - "runOptions": { - "runOn": "folderOpen" } }, { @@ -84,6 +81,7 @@ "type": "gulp", "task": "hygiene", "problemMatcher": [] - } + }, + ] } diff --git a/.yarnrc b/.yarnrc index b32ae136d49..c45abdbacad 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://atom.io/download/electron" -target "3.0.13" +target "4.2.7" runtime "electron" diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 65c8a42b8d2..00000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1 +0,0 @@ -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7775753e8bc..34703fae665 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,7 +37,6 @@ If you find your issue already exists, make relevant comments and add your [reac * 👍 - upvote * 👎 - downvote - If you cannot find an existing issue that describes your bug or feature, create a new issue using the guidelines below. ### Writing Good Bug Reports and Feature Requests @@ -52,7 +51,9 @@ The built-in tool for reporting an issue, which you can access by using `Report Please include the following with each issue: -* Version of VS Code +* Version of VS Code + +* Your operating system * List of extensions that you have installed diff --git a/README.md b/README.md index a7294e71b9b..035ba940a62 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,68 @@ -# Visual Studio Code - Open Source +# Visual Studio Code - Open Source ("Code - OSS") -[![Build Status](https://vscode.visualstudio.com/_apis/public/build/definitions/a4cdce18-a05c-4bb8-9476-5d07e63bfd76/1/badge?branchName=master)](https://aka.ms/vscode-builds) + +[![Build Status](https://dev.azure.com/vscode/VSCode/_apis/build/status/VS%20Code?branchName=master)](https://dev.azure.com/vscode/VSCode/_build/latest?definitionId=12) [![Feature Requests](https://img.shields.io/github/issues/Microsoft/vscode/feature-request.svg)](https://github.com/Microsoft/vscode/issues?q=is%3Aopen+is%3Aissue+label%3Afeature-request+sort%3Areactions-%2B1-desc) [![Bugs](https://img.shields.io/github/issues/Microsoft/vscode/bug.svg)](https://github.com/Microsoft/vscode/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3Abug) [![Gitter](https://img.shields.io/badge/chat-on%20gitter-yellow.svg)](https://gitter.im/Microsoft/vscode) -[VS Code](https://code.visualstudio.com) is a type of tool that combines the simplicity of -a code editor with what developers need for their core edit-build-debug cycle. It provides comprehensive editing and debugging support, an extensibility model, and lightweight integration with existing tools. +## The Repository -VS Code is updated monthly with new features and bug fixes. You can download it for Windows, macOS, and Linux on [VS Code's website](https://code.visualstudio.com/Download). To get the latest releases every day, you can install the [Insiders version of VS Code](https://code.visualstudio.com/insiders). This builds from the master branch and is updated daily at the very least. +This repository ("`Code - OSS`") is where we (Microsoft) develop the [Visual Studio Code](https://code.visualstudio.com) product. Not only do we work on code and issues here, we also publish our roadmap, monthly iteration plans, and our endgame plans. The source code here is available to everyone under the standard [MIT license](https://github.com/microsoft/vscode/blob/master/LICENSE.txt). + +## Visual Studio Code

- VS Code in action + VS Code in action

-The [`vscode`](https://github.com/microsoft/vscode) repository is where VS Code is developed and there are many ways you can participate in the project, for example: +[Visual Studio Code](https://code.visualstudio.com) is a distribution of the `Code - OSS` repository with Microsoft specific customizations released under a traditional [Microsoft product license](https://code.visualstudio.com/License/). + +[Visual Studio Code](https://code.visualstudio.com) combines the simplicity of a code editor with what developers need for their core edit-build-debug cycle. It provides comprehensive code editing, navigation, and understanding support along with lightweight debugging, a rich extensibility model, and lightweight integration with existing tools. + +Visual Studio Code is updated monthly with new features and bug fixes. You can download it for Windows, macOS, and Linux on [Visual Studio Code's website](https://code.visualstudio.com/Download). To get the latest releases every day, install the [Insiders build](https://code.visualstudio.com/insiders). + -* [Submit bugs and feature requests](https://github.com/microsoft/vscode/issues) and help us verify as they are checked in. -* Review [source code changes](https://github.com/microsoft/vscode/pulls). -* Review the [documentation](https://github.com/microsoft/vscode-docs) and make pull requests for anything from typos to new content. ## Contributing +There are many ways in which you can participate in the project, for example: + +* [Submit bugs and feature requests](https://github.com/microsoft/vscode/issues), and help us verify as they are checked in +* Review [source code changes](https://github.com/microsoft/vscode/pulls) +* Review the [documentation](https://github.com/microsoft/vscode-docs) and make pull requests for anything from typos to new content + If you are interested in fixing issues and contributing directly to the code base, please see the document [How to Contribute](https://github.com/Microsoft/vscode/wiki/How-to-Contribute), which covers the following: * [How to build and run from source](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#build-and-run) * [The development workflow, including debugging and running tests](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#debugging) -* [Coding Guidelines](https://github.com/Microsoft/vscode/wiki/Coding-Guidelines) +* [Coding guidelines](https://github.com/Microsoft/vscode/wiki/Coding-Guidelines) * [Submitting pull requests](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#pull-requests) * [Contributing to translations](https://aka.ms/vscodeloc) -Please also see our [Code of Conduct](CODE_OF_CONDUCT.md). - ## Feedback -* Ask a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/vscode). -* Request a new feature on [GitHub](CONTRIBUTING.md). -* Vote for [Popular Feature Requests](https://github.com/Microsoft/vscode/issues?q=is%3Aopen+is%3Aissue+label%3Afeature-request+sort%3Areactions-%2B1-desc). -* File a bug in [GitHub Issues](https://github.com/Microsoft/vscode/issues). -* [Tweet](https://twitter.com/code) us with any other feedback. +* Ask a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/vscode) +* [Request a new feature](CONTRIBUTING.md) +* Up vote [popular feature requests](https://github.com/Microsoft/vscode/issues?q=is%3Aopen+is%3Aissue+label%3Afeature-request+sort%3Areactions-%2B1-desc) +* [File an issue](https://github.com/Microsoft/vscode/issues) +* Follow [@code](https://twitter.com/code) and let us know what you think! ## Related Projects -Many of the core components and extensions to Code live in their own repositories on GitHub. For example, the [node debug adapter](https://github.com/microsoft/vscode-node-debug) and the [mono debug adapter](https://github.com/microsoft/vscode-mono-debug) have their own repositories. - -For a complete list, please visit the [Related Projects](https://github.com/Microsoft/vscode/wiki/Related-Projects) page on our [wiki](https://github.com/Microsoft/vscode/wiki). +Many of the core components and extensions to Code live in their own repositories on GitHub. For example, the [node debug adapter](https://github.com/microsoft/vscode-node-debug) and the [mono debug adapter](https://github.com/microsoft/vscode-mono-debug) have their own repositories. For a complete list, please visit the [Related Projects](https://github.com/Microsoft/vscode/wiki/Related-Projects) page on our [wiki](https://github.com/Microsoft/vscode/wiki). ## Bundled Extensions -Code ships with a set of extensions. These extensions are located in the [extensions](extensions) folder. -These extensions include grammars and snippets for several languages. Extensions that provide rich language support (code completion, go to definition) for a language have the suffix 'language-features'. For example, the 'json' extension provides coloring for JSON and the 'json-language-features' provides rich language support for JSON. +Code includes a set of built-in extensions located in the [extensions](extensions) folder, including grammars and snippets for many languages. Extensions that provide rich language support (code completion, Go to Definition) for a language have the suffix `language-features`. For example, the `json` extension provides coloring for `JSON` and the `json-language-features` provides rich language support for `JSON`. + +## Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. ## License Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the [MIT](LICENSE.txt) License. +Licensed under the [MIT](LICENSE.txt) license. diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index 4541dbbb24d..64f72e53be0 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -5,106 +5,70 @@ Do Not Translate or Localize This project incorporates components from the projects listed below. The original copyright notices and the licenses under which Microsoft received such components are set forth below. Microsoft reserves all rights not expressly granted herein, whether by implication, estoppel or otherwise. -1. atom/language-c (https://github.com/atom/language-c) -2. atom/language-clojure (https://github.com/atom/language-clojure) -3. atom/language-coffee-script (https://github.com/atom/language-coffee-script) -4. atom/language-css (https://github.com/atom/language-css) -5. atom/language-java (https://github.com/atom/language-java) -6. atom/language-objective-c (https://github.com/atom/language-objective-c) -7. atom/language-sass version 0.52.0 (https://github.com/atom/language-sass) -8. atom/language-shellscript (https://github.com/atom/language-shellscript) -9. atom/language-xml (https://github.com/atom/language-xml) -10. chriskempson/tomorrow-theme (https://github.com/chriskempson/tomorrow-theme) -11. Colorsublime-Themes version 0.1.0 (https://github.com/Colorsublime/Colorsublime-Themes) -12. daaain/Handlebars (https://github.com/daaain/Handlebars) -13. davidrios/pug-tmbundle (https://github.com/davidrios/pug-tmbundle) -14. definitelytyped (https://github.com/DefinitelyTyped/DefinitelyTyped) -15. demyte/language-cshtml (https://github.com/demyte/language-cshtml) -16. Document Object Model version 4.0.0 (https://www.w3.org/DOM/) -17. dotnet/csharp-tmLanguage version 0.1.0 (https://github.com/dotnet/csharp-tmLanguage) -18. expand-abbreviation version 0.5.8 (https://github.com/emmetio/expand-abbreviation) -19. fadeevab/make.tmbundle (https://github.com/fadeevab/make.tmbundle) -20. freebroccolo/atom-language-swift (https://github.com/freebroccolo/atom-language-swift) -21. HTML 5.1 W3C Working Draft version 08 October 2015 (http://www.w3.org/TR/2015/WD-html51-20151008/) -22. Ikuyadeu/vscode-R (https://github.com/Ikuyadeu/vscode-R) -23. Ionic documentation version 1.2.4 (https://github.com/ionic-team/ionic-site) -24. ionide/ionide-fsgrammar (https://github.com/ionide/ionide-fsgrammar) -25. js-beautify version 1.6.8 (https://github.com/beautify-web/js-beautify) -26. Jxck/assert version 1.0.0 (https://github.com/Jxck/assert) -27. language-docker (https://github.com/moby/moby) -28. language-go version 0.39.0 (https://github.com/atom/language-go) -29. language-less (https://github.com/atom/language-less) -30. language-php (https://github.com/atom/language-php) -31. language-rust version 0.4.9 (https://github.com/zargony/atom-language-rust) -32. MagicStack/MagicPython (https://github.com/MagicStack/MagicPython) -33. marked version 0.5.0 (https://github.com/markedjs/marked) -34. mdn-data version 1.1.12 (https://github.com/mdn/data) -35. Microsoft/TypeScript-TmLanguage version 0.0.1 (https://github.com/Microsoft/TypeScript-TmLanguage) -36. Microsoft/vscode-JSON.tmLanguage (https://github.com/Microsoft/vscode-JSON.tmLanguage) -37. Microsoft/vscode-mssql (https://github.com/Microsoft/vscode-mssql) -38. mmims/language-batchfile (https://github.com/mmims/language-batchfile) -39. octicons-code version 3.1.0 (https://registry.npmjs.org/octicons/-/octicons-3.1.0.tgz) -40. octicons-font version 3.1.0 (https://registry.npmjs.org/octicons/-/octicons-3.1.0.tgz) -41. PowerShell/EditorSyntax (https://github.com/powershell/editorsyntax) -42. seti-ui version 0.1.0 (https://github.com/jesseweed/seti-ui) -43. shaders-tmLanguage version 0.1.0 (https://github.com/tgjones/shaders-tmLanguage) -44. textmate/asp.vb.net.tmbundle (https://github.com/textmate/asp.vb.net.tmbundle) -45. textmate/c.tmbundle (https://github.com/textmate/c.tmbundle) -46. textmate/diff.tmbundle (https://github.com/textmate/diff.tmbundle) -47. textmate/git.tmbundle (https://github.com/textmate/git.tmbundle) -48. textmate/groovy.tmbundle (https://github.com/textmate/groovy.tmbundle) -49. textmate/html.tmbundle (https://github.com/textmate/html.tmbundle) -50. textmate/ini.tmbundle (https://github.com/textmate/ini.tmbundle) -51. textmate/javascript.tmbundle (https://github.com/textmate/javascript.tmbundle) -52. textmate/lua.tmbundle (https://github.com/textmate/lua.tmbundle) -53. textmate/markdown.tmbundle (https://github.com/textmate/markdown.tmbundle) -54. textmate/perl.tmbundle (https://github.com/textmate/perl.tmbundle) -55. textmate/ruby.tmbundle (https://github.com/textmate/ruby.tmbundle) -56. textmate/yaml.tmbundle (https://github.com/textmate/yaml.tmbundle) -57. TypeScript-TmLanguage version 0.1.8 (https://github.com/Microsoft/TypeScript-TmLanguage) +1. atom/language-clojure version 0.22.7 (https://github.com/atom/language-clojure) +2. atom/language-coffee-script version 0.49.3 (https://github.com/atom/language-coffee-script) +3. atom/language-java version 0.31.3 (https://github.com/atom/language-java) +4. atom/language-sass version 0.61.4 (https://github.com/atom/language-sass) +5. atom/language-shellscript version 0.26.0 (https://github.com/atom/language-shellscript) +6. atom/language-xml version 0.35.2 (https://github.com/atom/language-xml) +7. Colorsublime-Themes version 0.1.0 (https://github.com/Colorsublime/Colorsublime-Themes) +8. daaain/Handlebars version 1.8.0 (https://github.com/daaain/Handlebars) +9. davidrios/pug-tmbundle (https://github.com/davidrios/pug-tmbundle) +10. definitelytyped (https://github.com/DefinitelyTyped/DefinitelyTyped) +11. demyte/language-cshtml version 0.3.0 (https://github.com/demyte/language-cshtml) +12. Document Object Model version 4.0.0 (https://www.w3.org/DOM/) +13. dotnet/csharp-tmLanguage version 0.1.0 (https://github.com/dotnet/csharp-tmLanguage) +14. expand-abbreviation version 0.5.8 (https://github.com/emmetio/expand-abbreviation) +15. fadeevab/make.tmbundle (https://github.com/fadeevab/make.tmbundle) +16. freebroccolo/atom-language-swift (https://github.com/freebroccolo/atom-language-swift) +17. HTML 5.1 W3C Working Draft version 08 October 2015 (http://www.w3.org/TR/2015/WD-html51-20151008/) +18. Ikuyadeu/vscode-R version 0.5.5 (https://github.com/Ikuyadeu/vscode-R) +19. Ionic documentation version 1.2.4 (https://github.com/ionic-team/ionic-site) +20. ionide/ionide-fsgrammar (https://github.com/ionide/ionide-fsgrammar) +21. jeff-hykin/cpp-textmate-grammar version 1.12.11 (https://github.com/jeff-hykin/cpp-textmate-grammar) +22. jeff-hykin/cpp-textmate-grammar version 1.12.18 (https://github.com/jeff-hykin/cpp-textmate-grammar) +23. js-beautify version 1.6.8 (https://github.com/beautify-web/js-beautify) +24. Jxck/assert version 1.0.0 (https://github.com/Jxck/assert) +25. language-docker (https://github.com/moby/moby) +26. language-go version 0.44.3 (https://github.com/atom/language-go) +27. language-less version 0.34.2 (https://github.com/atom/language-less) +28. language-php version 0.44.1 (https://github.com/atom/language-php) +29. language-rust version 0.4.12 (https://github.com/zargony/atom-language-rust) +30. MagicStack/MagicPython version 1.1.1 (https://github.com/MagicStack/MagicPython) +31. marked version 0.6.2 (https://github.com/markedjs/marked) +32. mdn-data version 1.1.12 (https://github.com/mdn/data) +33. Microsoft/TypeScript-TmLanguage version 0.0.1 (https://github.com/Microsoft/TypeScript-TmLanguage) +34. Microsoft/vscode-JSON.tmLanguage (https://github.com/Microsoft/vscode-JSON.tmLanguage) +35. Microsoft/vscode-mssql version 1.6.0 (https://github.com/Microsoft/vscode-mssql) +36. mmims/language-batchfile version 0.7.5 (https://github.com/mmims/language-batchfile) +37. octicons version 8.3.0 (https://github.com/primer/octicons) +38. octref/language-css version 0.42.11 (https://github.com/octref/language-css) +39. PowerShell/EditorSyntax (https://github.com/powershell/editorsyntax) +40. promise-polyfill version 8.0.0 (https://github.com/taylorhakes/promise-polyfill) +41. seti-ui version 0.1.0 (https://github.com/jesseweed/seti-ui) +42. shaders-tmLanguage version 0.1.0 (https://github.com/tgjones/shaders-tmLanguage) +43. textmate/asp.vb.net.tmbundle (https://github.com/textmate/asp.vb.net.tmbundle) +44. textmate/c.tmbundle (https://github.com/textmate/c.tmbundle) +45. textmate/diff.tmbundle (https://github.com/textmate/diff.tmbundle) +46. textmate/git.tmbundle (https://github.com/textmate/git.tmbundle) +47. textmate/groovy.tmbundle (https://github.com/textmate/groovy.tmbundle) +48. textmate/html.tmbundle (https://github.com/textmate/html.tmbundle) +49. textmate/ini.tmbundle (https://github.com/textmate/ini.tmbundle) +50. textmate/javascript.tmbundle (https://github.com/textmate/javascript.tmbundle) +51. textmate/lua.tmbundle (https://github.com/textmate/lua.tmbundle) +52. textmate/markdown.tmbundle (https://github.com/textmate/markdown.tmbundle) +53. textmate/perl.tmbundle (https://github.com/textmate/perl.tmbundle) +54. textmate/ruby.tmbundle (https://github.com/textmate/ruby.tmbundle) +55. textmate/yaml.tmbundle (https://github.com/textmate/yaml.tmbundle) +56. TypeScript-TmLanguage version 0.1.8 (https://github.com/Microsoft/TypeScript-TmLanguage) +57. TypeScript-TmLanguage version 1.0.0 (https://github.com/Microsoft/TypeScript-TmLanguage) 58. Unicode version 12.0.0 (http://www.unicode.org/) -59. vscode-logfile-highlighter version 1.2.0 (https://github.com/emilast/vscode-logfile-highlighter) -60. vscode-swift version 0.0.1 (https://github.com/owensd/vscode-swift) -61. Web Background Synchronization (https://github.com/WICG/BackgroundSync) +59. vscode-logfile-highlighter version 2.4.1 (https://github.com/emilast/vscode-logfile-highlighter) +60. vscode-octicons-font version 1.3.1 (https://github.com/Microsoft/vscode-octicons-font) +61. vscode-swift version 0.0.1 (https://github.com/owensd/vscode-swift) +62. Web Background Synchronization (https://github.com/WICG/BackgroundSync) -%% atom/language-c NOTICES AND INFORMATION BEGIN HERE -========================================= -The MIT License (MIT) - -Copyright (c) 2014 GitHub Inc. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -This package was derived from a TextMate bundle located at -https://github.com/textmate/c.tmbundle and distributed under the following -license, located in `README.mdown`: - -Permission to copy, use, modify, sell and distribute this -software is granted. This software is provided "as is" without -express or implied warranty, and with no claim as to its -suitability for any purpose. -========================================= -END OF atom/language-c NOTICES AND INFORMATION - %% atom/language-clojure NOTICES AND INFORMATION BEGIN HERE ========================================= Copyright (c) 2014 GitHub Inc. @@ -212,43 +176,6 @@ OTHER DEALINGS IN THE SOFTWARE. ========================================= END OF atom/language-coffee-script NOTICES AND INFORMATION -%% atom/language-css NOTICES AND INFORMATION BEGIN HERE -========================================= -The MIT License (MIT) - -Copyright (c) 2014 GitHub Inc. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -This package was derived from a TextMate bundle located at -https://github.com/textmate/css.tmbundle and distributed under the following -license, located in `README.mdown`: - -Permission to copy, use, modify, sell and distribute this -software is granted. This software is provided "as is" without -express or implied warranty, and with no claim as to its -suitability for any purpose. -========================================= -END OF atom/language-css NOTICES AND INFORMATION - %% atom/language-java NOTICES AND INFORMATION BEGIN HERE ========================================= The MIT License (MIT) @@ -286,43 +213,6 @@ suitability for any purpose. ========================================= END OF atom/language-java NOTICES AND INFORMATION -%% atom/language-objective-c NOTICES AND INFORMATION BEGIN HERE -========================================= -The MIT License (MIT) - -Copyright (c) 2014 GitHub Inc. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -This package was derived from a TextMate bundle located at -https://github.com/textmate/objective-c.tmbundle and distributed under the following -license, located in `README.mdown`: - -Permission to copy, use, modify, sell and distribute this -software is granted. This software is provided "as is" without -express or implied warranty, and with no claim as to its -suitability for any purpose. -========================================= -END OF atom/language-objective-c NOTICES AND INFORMATION - %% atom/language-sass NOTICES AND INFORMATION BEGIN HERE ========================================= The MIT License (MIT) @@ -450,22 +340,6 @@ suitability for any purpose. ========================================= END OF atom/language-xml NOTICES AND INFORMATION -%% chriskempson/tomorrow-theme NOTICES AND INFORMATION BEGIN HERE -========================================= -The MIT License (MIT) - -Copyright (C) 2013 Chris Kempson - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -========================================= -END OF chriskempson/tomorrow-theme NOTICES AND INFORMATION - %% Colorsublime-Themes NOTICES AND INFORMATION BEGIN HERE ========================================= Copyright (c) 2015 Colorsublime.com @@ -825,6 +699,32 @@ THE SOFTWARE. ========================================= END OF ionide/ionide-fsgrammar NOTICES AND INFORMATION +%% jeff-hykin/cpp-textmate-grammar NOTICES AND INFORMATION BEGIN HERE +========================================= +MIT License + +Copyright (c) 2019 Jeff Hykin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +========================================= +END OF jeff-hykin/cpp-textmate-grammar NOTICES AND INFORMATION + %% js-beautify NOTICES AND INFORMATION BEGIN HERE ========================================= The MIT License (MIT) @@ -1800,11 +1700,11 @@ THE SOFTWARE. ========================================= END OF mmims/language-batchfile NOTICES AND INFORMATION -%% octicons-code NOTICES AND INFORMATION BEGIN HERE +%% octicons NOTICES AND INFORMATION BEGIN HERE ========================================= -The MIT License (MIT) +MIT License -(c) 2012-2015 GitHub +Copyright (c) 2019 GitHub Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -1813,109 +1713,55 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. ========================================= -END OF octicons-code NOTICES AND INFORMATION +END OF octicons NOTICES AND INFORMATION -%% octicons-font NOTICES AND INFORMATION BEGIN HERE +%% octref/language-css NOTICES AND INFORMATION BEGIN HERE ========================================= -(c) 2012-2015 GitHub +The MIT License (MIT) -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +Copyright (c) 2014 GitHub Inc. -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. +This package was derived from a TextMate bundle located at +https://github.com/textmate/css.tmbundle and distributed under the following +license, located in `README.mdown`: -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. +Permission to copy, use, modify, sell and distribute this +software is granted. This software is provided "as is" without +express or implied warranty, and with no claim as to its +suitability for any purpose. ========================================= -END OF octicons-font NOTICES AND INFORMATION +END OF octref/language-css NOTICES AND INFORMATION %% PowerShell/EditorSyntax NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -1945,6 +1791,33 @@ SOFTWARE. ========================================= END OF PowerShell/EditorSyntax NOTICES AND INFORMATION +%% promise-polyfill NOTICES AND INFORMATION BEGIN HERE +========================================= +The MIT License (MIT) + +Copyright (c) 2014 Taylor Hakes +Copyright (c) 2014 Forbes Lindesay + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +========================================= +END OF promise-polyfill NOTICES AND INFORMATION + %% seti-ui NOTICES AND INFORMATION BEGIN HERE ========================================= Copyright (c) 2014 Jesse Weed @@ -2357,6 +2230,32 @@ SOFTWARE. ========================================= END OF vscode-logfile-highlighter NOTICES AND INFORMATION +%% vscode-octicons-font NOTICES AND INFORMATION BEGIN HERE +========================================= +MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE +========================================= +END OF vscode-octicons-font NOTICES AND INFORMATION + %% vscode-swift NOTICES AND INFORMATION BEGIN HERE ========================================= The MIT License (MIT) diff --git a/build/.cachesalt b/build/.cachesalt new file mode 100644 index 00000000000..105ce86ae3c --- /dev/null +++ b/build/.cachesalt @@ -0,0 +1 @@ +2019-07-11T05:47:05.444Z diff --git a/build/.nativeignore b/build/.nativeignore new file mode 100644 index 00000000000..a4823bf719c --- /dev/null +++ b/build/.nativeignore @@ -0,0 +1,107 @@ +# cleanup rules for native node modules, .gitignore style + +nan/** +*/node_modules/nan/** + +fsevents/binding.gyp +fsevents/fsevents.cc +fsevents/build/** +fsevents/src/** +fsevents/test/** +!fsevents/**/*.node + +vscode-sqlite3/binding.gyp +vscode-sqlite3/benchmark/** +vscode-sqlite3/cloudformation/** +vscode-sqlite3/deps/** +vscode-sqlite3/test/** +vscode-sqlite3/build/** +vscode-sqlite3/src/** +!vscode-sqlite3/build/Release/*.node + +oniguruma/binding.gyp +oniguruma/build/** +oniguruma/src/** +oniguruma/deps/** +!oniguruma/build/Release/*.node +!oniguruma/src/*.js + +windows-mutex/binding.gyp +windows-mutex/build/** +windows-mutex/src/** +!windows-mutex/**/*.node + +native-keymap/binding.gyp +native-keymap/build/** +native-keymap/src/** +native-keymap/deps/** +!native-keymap/build/Release/*.node + +native-is-elevated/binding.gyp +native-is-elevated/build/** +native-is-elevated/src/** +native-is-elevated/deps/** +!native-is-elevated/build/Release/*.node + +native-watchdog/binding.gyp +native-watchdog/build/** +native-watchdog/src/** +!native-watchdog/build/Release/*.node + +spdlog/binding.gyp +spdlog/build/** +spdlog/deps/** +spdlog/src/** +spdlog/test/** +!spdlog/build/Release/*.node + +jschardet/dist/** + +windows-foreground-love/binding.gyp +windows-foreground-love/build/** +windows-foreground-love/src/** +!windows-foreground-love/**/*.node + +windows-process-tree/binding.gyp +windows-process-tree/build/** +windows-process-tree/src/** +!windows-process-tree/**/*.node + +keytar/binding.gyp +keytar/build/** +keytar/src/** +keytar/script/** +keytar/node_modules/** +!keytar/**/*.node + +node-pty/binding.gyp +node-pty/build/** +node-pty/src/** +node-pty/tools/** +node-pty/deps/** +!node-pty/build/Release/*.exe +!node-pty/build/Release/*.dll +!node-pty/build/Release/*.node + +nsfw/binding.gyp +nsfw/build/** +nsfw/src/** +nsfw/openpa/** +nsfw/includes/** +!nsfw/build/Release/*.node +!nsfw/**/*.a + +vsda/build/** +vsda/ci/** +vsda/src/** +vsda/.gitignore +vsda/binding.gyp +vsda/README.md +vsda/targets +!vsda/build/Release/vsda.node + +vscode-windows-ca-certs/**/* +!vscode-windows-ca-certs/package.json +!vscode-windows-ca-certs/**/*.node + +node-addon-api/**/* diff --git a/build/azure-pipelines/common/extract-telemetry.sh b/build/azure-pipelines/common/extract-telemetry.sh new file mode 100755 index 00000000000..84bbd9c537c --- /dev/null +++ b/build/azure-pipelines/common/extract-telemetry.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -e + +cd $BUILD_STAGINGDIRECTORY +mkdir extraction +cd extraction +git clone --depth 1 https://github.com/Microsoft/vscode-extension-telemetry.git +git clone --depth 1 https://github.com/Microsoft/vscode-chrome-debug-core.git +git clone --depth 1 https://github.com/Microsoft/vscode-node-debug2.git +git clone --depth 1 https://github.com/Microsoft/vscode-node-debug.git +git clone --depth 1 https://github.com/Microsoft/vscode-html-languageservice.git +git clone --depth 1 https://github.com/Microsoft/vscode-json-languageservice.git +$BUILD_SOURCESDIRECTORY/build/node_modules/.bin/vscode-telemetry-extractor --sourceDir $BUILD_SOURCESDIRECTORY --excludedDir $BUILD_SOURCESDIRECTORY/extensions --outputDir . --applyEndpoints +$BUILD_SOURCESDIRECTORY/build/node_modules/.bin/vscode-telemetry-extractor --config $BUILD_SOURCESDIRECTORY/build/azure-pipelines/common/telemetry-config.json -o . +mkdir -p $BUILD_SOURCESDIRECTORY/.build/telemetry +mv declarations-resolved.json $BUILD_SOURCESDIRECTORY/.build/telemetry/telemetry-core.json +mv config-resolved.json $BUILD_SOURCESDIRECTORY/.build/telemetry/telemetry-extensions.json +cd .. +rm -rf extraction \ No newline at end of file diff --git a/build/azure-pipelines/common/installDistro.ts b/build/azure-pipelines/common/installDistro.ts deleted file mode 100644 index 3cb97afd273..00000000000 --- a/build/azure-pipelines/common/installDistro.ts +++ /dev/null @@ -1,18 +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 * as cp from 'child_process'; - -function yarnInstall(packageName: string): void { - cp.execSync(`yarn add --no-lockfile ${packageName}`); -} - -const product = require('../../../product.json'); -const dependencies = product.dependencies || {} as { [name: string]: string; }; - -Object.keys(dependencies).forEach(name => { - const url = dependencies[name]; - yarnInstall(url); -}); \ No newline at end of file diff --git a/build/azure-pipelines/common/publish.ts b/build/azure-pipelines/common/publish.ts index 2095c2d2532..62113c8f3b3 100644 --- a/build/azure-pipelines/common/publish.ts +++ b/build/azure-pipelines/common/publish.ts @@ -6,7 +6,6 @@ 'use strict'; import * as fs from 'fs'; -import { execSync } from 'child_process'; import { Readable } from 'stream'; import * as crypto from 'crypto'; import * as azure from 'azure-storage'; @@ -65,7 +64,7 @@ interface Asset { platform: string; type: string; url: string; - mooncakeUrl: string; + mooncakeUrl?: string; hash: string; sha256hash: string; size: number; @@ -152,9 +151,6 @@ async function publish(commit: string, quality: string, platform: string, type: const queuedBy = process.env['BUILD_QUEUEDBY']!; const sourceBranch = process.env['BUILD_SOURCEBRANCH']!; - const isReleased = quality === 'insider' - && /^master$|^refs\/heads\/master$/.test(sourceBranch) - && /Project Collection Service Accounts|Microsoft.VisualStudio.Services.TFS/.test(queuedBy); console.log('Publishing...'); console.log('Quality:', quality); @@ -164,7 +160,6 @@ async function publish(commit: string, quality: string, platform: string, type: console.log('Version:', version); console.log('Commit:', commit); console.log('Is Update:', isUpdate); - console.log('Is Released:', isReleased); console.log('File:', file); const stat = await new Promise((c, e) => fs.stat(file, (err, stat) => err ? e(err) : c(stat))); @@ -184,40 +179,18 @@ async function publish(commit: string, quality: string, platform: string, type: const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']!) .withFilter(new azure.ExponentialRetryPolicyFilter(20)); - const mooncakeBlobService = azure.createBlobService(storageAccount, process.env['MOONCAKE_STORAGE_ACCESS_KEY']!, `${storageAccount}.blob.core.chinacloudapi.cn`) - .withFilter(new azure.ExponentialRetryPolicyFilter(20)); + await assertContainer(blobService, quality); - // mooncake is fussy and far away, this is needed! - mooncakeBlobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000; + const blobExists = await doesAssetExist(blobService, quality, blobName); - await Promise.all([ - assertContainer(blobService, quality), - assertContainer(mooncakeBlobService, quality) - ]); - - const [blobExists, moooncakeBlobExists] = await Promise.all([ - doesAssetExist(blobService, quality, blobName), - doesAssetExist(mooncakeBlobService, quality, blobName) - ]); - - const promises: Array> = []; - - if (!blobExists) { - promises.push(uploadBlob(blobService, quality, blobName, file)); - } - - if (!moooncakeBlobExists) { - promises.push(uploadBlob(mooncakeBlobService, quality, blobName, file)); - } - - if (promises.length === 0) { + if (blobExists) { console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`); return; } console.log('Uploading blobs to Azure storage...'); - await Promise.all(promises); + await uploadBlob(blobService, quality, blobName, file); console.log('Blobs successfully uploaded.'); @@ -229,7 +202,6 @@ async function publish(commit: string, quality: string, platform: string, type: platform: platform, type: type, url: `${process.env['AZURE_CDN_URL']}/${quality}/${blobName}`, - mooncakeUrl: `${process.env['MOONCAKE_CDN_URL']}/${quality}/${blobName}`, hash: sha1hash, sha256hash, size @@ -246,7 +218,7 @@ async function publish(commit: string, quality: string, platform: string, type: id: commit, timestamp: (new Date()).getTime(), version, - isReleased: config.frozen ? false : isReleased, + isReleased: false, sourceBranch, queuedBy, assets: [] as Array, @@ -265,8 +237,10 @@ async function publish(commit: string, quality: string, platform: string, type: } function main(): void { - if (process.env['VSCODE_BUILD_SKIP_PUBLISH']) { - console.warn('Skipping publish due to VSCODE_BUILD_SKIP_PUBLISH'); + const commit = process.env['BUILD_SOURCEVERSION']; + + if (!commit) { + console.warn('Skipping publish due to missing BUILD_SOURCEVERSION'); return; } @@ -275,7 +249,6 @@ function main(): void { }); const [quality, platform, type, name, version, _isUpdate, file] = opts._; - const commit = execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim(); publish(commit, quality, platform, type, name, version, _isUpdate, file, opts).catch(err => { console.error(err); diff --git a/build/azure-pipelines/common/release.ts b/build/azure-pipelines/common/release.ts new file mode 100644 index 00000000000..1220bd62e68 --- /dev/null +++ b/build/azure-pipelines/common/release.ts @@ -0,0 +1,109 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { DocumentClient } from 'documentdb'; + +interface Config { + id: string; + frozen: boolean; +} + +function createDefaultConfig(quality: string): Config { + return { + id: quality, + frozen: false + }; +} + +function getConfig(quality: string): Promise { + const client = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT']!, { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); + const collection = 'dbs/builds/colls/config'; + const query = { + query: `SELECT TOP 1 * FROM c WHERE c.id = @quality`, + parameters: [ + { name: '@quality', value: quality } + ] + }; + + return new Promise((c, e) => { + client.queryDocuments(collection, query).toArray((err, results) => { + if (err && err.code !== 409) { return e(err); } + + c(!results || results.length === 0 ? createDefaultConfig(quality) : results[0] as any as Config); + }); + }); +} + +function doRelease(commit: string, quality: string): Promise { + const client = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT']!, { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); + const collection = 'dbs/builds/colls/' + quality; + const query = { + query: 'SELECT TOP 1 * FROM c WHERE c.id = @id', + parameters: [{ name: '@id', value: commit }] + }; + + let updateTries = 0; + + function update(): Promise { + updateTries++; + + return new Promise((c, e) => { + client.queryDocuments(collection, query).toArray((err, results) => { + if (err) { return e(err); } + if (results.length !== 1) { return e(new Error('No documents')); } + + const release = results[0]; + release.isReleased = true; + + client.replaceDocument(release._self, release, err => { + if (err && err.code === 409 && updateTries < 5) { return c(update()); } + if (err) { return e(err); } + + console.log('Build successfully updated.'); + c(); + }); + }); + }); + } + + return update(); +} + +async function release(commit: string, quality: string): Promise { + const config = await getConfig(quality); + + console.log('Quality config:', config); + + if (config.frozen) { + console.log(`Skipping release because quality ${quality} is frozen.`); + return; + } + + await doRelease(commit, quality); +} + +function env(name: string): string { + const result = process.env[name]; + + if (!result) { + throw new Error(`Skipping release due to missing env: ${name}`); + } + + return result; +} + +async function main(): Promise { + const commit = env('BUILD_SOURCEVERSION'); + const quality = env('VSCODE_QUALITY'); + + await release(commit, quality); +} + +main().catch(err => { + console.error(err); + process.exit(1); +}); diff --git a/build/azure-pipelines/common/symbols.ts b/build/azure-pipelines/common/symbols.ts index 1a5125295f3..153be4f25b1 100644 --- a/build/azure-pipelines/common/symbols.ts +++ b/build/azure-pipelines/common/symbols.ts @@ -36,7 +36,6 @@ export interface IVersionAccessor extends IApplicationAccessor { enum Platform { WIN_32 = 'win32-ia32', WIN_64 = 'win32-x64', - LINUX_32 = 'linux-ia32', LINUX_64 = 'linux-x64', MAC_OS = 'darwin-x64' } @@ -147,6 +146,10 @@ async function ensureVersionAndSymbols(options: IOptions) { // Check version does not exist console.log(`HockeyApp: checking for existing version ${options.versions.code} (${options.platform})`); const versions = await getVersions({ accessToken: options.access.hockeyAppToken, appId: options.access.hockeyAppId }); + if (!Array.isArray(versions.app_versions)) { + throw new Error(`Unexpected response: ${JSON.stringify(versions)}`); + } + if (versions.app_versions.some(v => v.version === options.versions.code)) { console.log(`HockeyApp: Returning without uploading symbols because version ${options.versions.code} (${options.platform}) was already found`); return; @@ -185,13 +188,17 @@ const hockeyAppToken = process.argv[3]; const is64 = process.argv[4] === 'x64'; const hockeyAppId = process.argv[5]; +if (process.argv.length !== 6) { + throw new Error(`HockeyApp: Unexpected number of arguments. Got ${process.argv}`); +} + let platform: Platform; if (process.platform === 'darwin') { platform = Platform.MAC_OS; } else if (process.platform === 'win32') { platform = is64 ? Platform.WIN_64 : Platform.WIN_32; } else { - platform = is64 ? Platform.LINUX_64 : Platform.LINUX_32; + platform = Platform.LINUX_64; } // Create version and upload symbols in HockeyApp @@ -212,7 +219,9 @@ if (repository && codeVersion && electronVersion && (product.quality === 'stable }).then(() => { console.log('HockeyApp: done'); }).catch(error => { - console.error(`HockeyApp: error (${error})`); + console.error(`HockeyApp: error ${error} (AppID: ${hockeyAppId})`); + + return process.exit(1); }); } else { console.log(`HockeyApp: skipping due to unexpected context (repository: ${repository}, codeVersion: ${codeVersion}, electronVersion: ${electronVersion}, quality: ${product.quality})`); diff --git a/build/azure-pipelines/common/sync-mooncake.ts b/build/azure-pipelines/common/sync-mooncake.ts new file mode 100644 index 00000000000..1eac8f34e92 --- /dev/null +++ b/build/azure-pipelines/common/sync-mooncake.ts @@ -0,0 +1,171 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as url from 'url'; +import * as azure from 'azure-storage'; +import * as mime from 'mime'; +import { DocumentClient, RetrievedDocument } from 'documentdb'; + +function log(...args: any[]) { + console.log(...[`[${new Date().toISOString()}]`, ...args]); +} + +function error(...args: any[]) { + console.error(...[`[${new Date().toISOString()}]`, ...args]); +} + +if (process.argv.length < 3) { + error('Usage: node sync-mooncake.js '); + process.exit(-1); +} + +interface Build extends RetrievedDocument { + assets: Asset[]; +} + +interface Asset { + platform: string; + type: string; + url: string; + mooncakeUrl: string; + hash: string; + sha256hash: string; + size: number; + supportsFastUpdate?: boolean; +} + +function updateBuild(commit: string, quality: string, platform: string, type: string, asset: Asset): Promise { + const client = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT']!, { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); + const collection = 'dbs/builds/colls/' + quality; + const updateQuery = { + query: 'SELECT TOP 1 * FROM c WHERE c.id = @id', + parameters: [{ name: '@id', value: commit }] + }; + + let updateTries = 0; + + function _update(): Promise { + updateTries++; + + return new Promise((c, e) => { + client.queryDocuments(collection, updateQuery).toArray((err, results) => { + if (err) { return e(err); } + if (results.length !== 1) { return e(new Error('No documents')); } + + const release = results[0]; + + release.assets = [ + ...release.assets.filter((a: any) => !(a.platform === platform && a.type === type)), + asset + ]; + + client.replaceDocument(release._self, release, err => { + if (err && err.code === 409 && updateTries < 5) { return c(_update()); } + if (err) { return e(err); } + + log('Build successfully updated.'); + c(); + }); + }); + }); + } + + return _update(); +} + +async function sync(commit: string, quality: string): Promise { + log(`Synchronizing Mooncake assets for ${quality}, ${commit}...`); + + const cosmosdb = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT']!, { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); + const collection = `dbs/builds/colls/${quality}`; + const query = { + query: 'SELECT TOP 1 * FROM c WHERE c.id = @id', + parameters: [{ name: '@id', value: commit }] + }; + + const build = await new Promise((c, e) => { + cosmosdb.queryDocuments(collection, query).toArray((err, results) => { + if (err) { return e(err); } + if (results.length !== 1) { return e(new Error('No documents')); } + c(results[0] as Build); + }); + }); + + log(`Found build for ${commit}, with ${build.assets.length} assets`); + + const storageAccount = process.env['AZURE_STORAGE_ACCOUNT_2']!; + + const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']!) + .withFilter(new azure.ExponentialRetryPolicyFilter(20)); + + const mooncakeBlobService = azure.createBlobService(storageAccount, process.env['MOONCAKE_STORAGE_ACCESS_KEY']!, `${storageAccount}.blob.core.chinacloudapi.cn`) + .withFilter(new azure.ExponentialRetryPolicyFilter(20)); + + // mooncake is fussy and far away, this is needed! + blobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000; + mooncakeBlobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000; + + for (const asset of build.assets) { + try { + const blobPath = url.parse(asset.url).path; + + if (!blobPath) { + throw new Error(`Failed to parse URL: ${asset.url}`); + } + + const blobName = blobPath.replace(/^\/\w+\//, ''); + + log(`Found ${blobName}`); + + if (asset.mooncakeUrl) { + log(` Already in Mooncake ✔️`); + continue; + } + + const readStream = blobService.createReadStream(quality, blobName, undefined!); + const blobOptions: azure.BlobService.CreateBlockBlobRequestOptions = { + contentSettings: { + contentType: mime.lookup(blobPath), + cacheControl: 'max-age=31536000, public' + } + }; + + const writeStream = mooncakeBlobService.createWriteStreamToBlockBlob(quality, blobName, blobOptions, undefined); + + log(` Uploading to Mooncake...`); + await new Promise((c, e) => readStream.pipe(writeStream).on('finish', c).on('error', e)); + + log(` Updating build in DB...`); + asset.mooncakeUrl = `${process.env['MOONCAKE_CDN_URL']}${blobPath}`; + await updateBuild(commit, quality, asset.platform, asset.type, asset); + + log(` Done ✔️`); + } catch (err) { + error(err); + } + } + + log(`All done ✔️`); +} + +function main(): void { + const commit = process.env['BUILD_SOURCEVERSION']; + + if (!commit) { + error('Skipping publish due to missing BUILD_SOURCEVERSION'); + return; + } + + const quality = process.argv[2]; + + sync(commit, quality).catch(err => { + error(err); + process.exit(1); + }); +} + +main(); diff --git a/build/azure-pipelines/common/telemetry-config.json b/build/azure-pipelines/common/telemetry-config.json new file mode 100644 index 00000000000..fcba1e042ba --- /dev/null +++ b/build/azure-pipelines/common/telemetry-config.json @@ -0,0 +1,72 @@ +[ + { + "eventPrefix": "typescript-language-features/", + "sourceDirs": [ + "../../s/extensions/typescript-language-features" + ], + "excludedDirs": [], + "applyEndpoints": true + }, + { + "eventPrefix": "git/", + "sourceDirs": [ + "../../s/extensions/git" + ], + "excludedDirs": [], + "applyEndpoints": true + }, + { + "eventPrefix": "extension-telemetry/", + "sourceDirs": [ + "vscode-extension-telemetry" + ], + "excludedDirs": [], + "applyEndpoints": true + }, + { + "eventPrefix": "vscode-markdown/", + "sourceDirs": [ + "../../s/extensions/markdown-language-features" + ], + "excludedDirs": [], + "applyEndpoints": true + }, + { + "eventPrefix": "html-language-features/", + "sourceDirs": [ + "../../s/extensions/html-language-features", + "vscode-html-languageservice" + ], + "excludedDirs": [], + "applyEndpoints": true + }, + { + "eventPrefix": "json-language-features/", + "sourceDirs": [ + "../../s/extensions/json-language-features", + "vscode-json-languageservice" + ], + "excludedDirs": [], + "applyEndpoints": true + }, + { + "eventPrefix": "ms-vscode.node2/", + "sourceDirs": [ + "vscode-chrome-debug-core", + "vscode-node-debug2" + ], + "excludedDirs": [], + "applyEndpoints": true, + "patchDebugEvents": true + }, + { + "eventPrefix": "ms-vscode.node/", + "sourceDirs": [ + "vscode-chrome-debug-core", + "vscode-node-debug" + ], + "excludedDirs": [], + "applyEndpoints": true, + "patchDebugEvents": true + } +] \ No newline at end of file diff --git a/build/azure-pipelines/darwin/continuous-build-darwin.yml b/build/azure-pipelines/darwin/continuous-build-darwin.yml index 99e17e940a6..018719423fe 100644 --- a/build/azure-pipelines/darwin/continuous-build-darwin.yml +++ b/build/azure-pipelines/darwin/continuous-build-darwin.yml @@ -1,13 +1,25 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "8.12.0" + versionSpec: "10.15.1" +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: '$(ArtifactFeed)' - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: versionSpec: "1.10.1" - script: | - yarn + yarn --frozen-lockfile displayName: Install Dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) +- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: '$(ArtifactFeed)' + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - script: | yarn gulp electron-x64 displayName: Download Electron @@ -17,9 +29,6 @@ steps: - script: | yarn monaco-compile-check displayName: Run Monaco Editor Checks -- script: | - yarn strict-null-check - displayName: Run Strict Null Checks - script: | yarn compile displayName: Compile Sources diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index ff9d32b35ca..b712e072849 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -1,29 +1,95 @@ steps: +- script: | + mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + displayName: Prepare cache flag + +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: 'build/.cachesalt, .build/commit' + targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' + vstsFeed: 'npm-vscode' + platformIndependent: true + alias: 'Compilation' + +- script: | + set -e + exit 1 + displayName: Check RestoreCache + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + - task: NodeTool@0 inputs: - versionSpec: "8.12.0" + versionSpec: "10.15.1" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: versionSpec: "1.10.1" -- script: | - set -e - echo "machine monacotools.visualstudio.com password $(VSO_PAT)" > ~/.netrc - yarn - yarn gulp -- hygiene - yarn monaco-compile-check - yarn strict-null-check - VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" yarn gulp -- mixin - node build/azure-pipelines/common/installDistro.js - node build/lib/builtInExtensions.js - displayName: Prepare build +- task: AzureKeyVault@1 + displayName: 'Azure Key Vault: Get Secrets' + inputs: + azureSubscription: 'vscode-builds-subscription' + KeyVaultName: vscode - script: | set -e - VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \ - AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \ - yarn gulp -- vscode-darwin-min upload-vscode-sourcemaps + + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF + + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling + +- script: | + set -e + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro + +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: 'npm-vscode' + +- script: | + set -e + CHILD_CONCURRENCY=1 yarn --frozen-lockfile + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + +- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: 'npm-vscode' + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + +- script: | + set -e + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + +- script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality + +- script: | + set -e + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-darwin-min-ci + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-reh-darwin-min-ci + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-reh-web-darwin-min-ci displayName: Build - script: | @@ -32,6 +98,13 @@ steps: # APP_NAME="`ls $(agent.builddirectory)/VSCode-darwin | head -n 1`" # yarn smoketest -- --build "$(agent.builddirectory)/VSCode-darwin/$APP_NAME" displayName: Run unit tests + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + +- script: | + set -e + ./scripts/test-integration.sh --build --tfs "Integration Tests" + displayName: Run integration tests + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | set -e @@ -59,31 +132,12 @@ steps: - script: | set -e - - # remove pkg from archive - zip -d ../VSCode-darwin.zip "*.pkg" - - # publish the build - PACKAGEJSON=`ls ../VSCode-darwin/*.app/Contents/Resources/app/package.json` - VERSION=`node -p "require(\"$PACKAGEJSON\").version"` - AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ - AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \ - MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \ - node build/azure-pipelines/common/publish.js \ - "$(VSCODE_QUALITY)" \ - darwin \ - archive \ - "VSCode-darwin-$(VSCODE_QUALITY).zip" \ - $VERSION \ - true \ - ../VSCode-darwin.zip - - # publish hockeyapp symbols - node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_MACOS)" - - # upload configuration - AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \ - yarn gulp -- upload-vscode-configuration + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + VSCODE_HOCKEYAPP_TOKEN="$(vscode-hockeyapp-token)" \ + ./build/azure-pipelines/darwin/publish.sh displayName: Publish - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 diff --git a/build/azure-pipelines/darwin/publish.sh b/build/azure-pipelines/darwin/publish.sh new file mode 100755 index 00000000000..fa453bcaff5 --- /dev/null +++ b/build/azure-pipelines/darwin/publish.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -e + +# remove pkg from archive +zip -d ../VSCode-darwin.zip "*.pkg" + +# publish the build +PACKAGEJSON=`ls ../VSCode-darwin/*.app/Contents/Resources/app/package.json` +VERSION=`node -p "require(\"$PACKAGEJSON\").version"` +node build/azure-pipelines/common/publish.js \ + "$VSCODE_QUALITY" \ + darwin \ + archive \ + "VSCode-darwin-$VSCODE_QUALITY.zip" \ + $VERSION \ + true \ + ../VSCode-darwin.zip + +# package Remote Extension Host +pushd .. && mv vscode-reh-darwin vscode-server-darwin && zip -Xry vscode-server-darwin.zip vscode-server-darwin && popd + +# publish Remote Extension Host +node build/azure-pipelines/common/publish.js \ + "$VSCODE_QUALITY" \ + server-darwin \ + archive-unsigned \ + "vscode-server-darwin.zip" \ + $VERSION \ + true \ + ../vscode-server-darwin.zip + +# publish hockeyapp symbols +node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" x64 "$VSCODE_HOCKEYAPP_ID_MACOS" + +# upload configuration +yarn gulp upload-vscode-configuration diff --git a/build/azure-pipelines/distro-build.yml b/build/azure-pipelines/distro-build.yml new file mode 100644 index 00000000000..62ee67ad1c6 --- /dev/null +++ b/build/azure-pipelines/distro-build.yml @@ -0,0 +1,42 @@ +trigger: + branches: + include: ['master', 'release/*'] +pr: + branches: + include: ['master', 'release/*'] + +steps: +- task: NodeTool@0 + inputs: + versionSpec: "10.15.1" + +- task: AzureKeyVault@1 + displayName: 'Azure Key Vault: Get Secrets' + inputs: + azureSubscription: 'vscode-builds-subscription' + KeyVaultName: vscode + +- script: | + set -e + + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF + + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + + git remote add distro "https://github.com/$VSCODE_MIXIN_REPO.git" + git fetch distro + + # Push master branch into oss/master + git push distro origin/master:refs/heads/oss/master + + # Push every release branch into oss/release + git for-each-ref --format="%(refname:short)" refs/remotes/origin/release/* | sed 's/^origin\/\(.*\)$/\0:refs\/heads\/oss\/\1/' | xargs git push distro + + git merge $(node -p "require('./package.json').distro") + + displayName: Sync & Merge Distro diff --git a/build/azure-pipelines/linux/continuous-build-linux.yml b/build/azure-pipelines/linux/continuous-build-linux.yml index fc124c5bf45..8b0aaca2ad9 100644 --- a/build/azure-pipelines/linux/continuous-build-linux.yml +++ b/build/azure-pipelines/linux/continuous-build-linux.yml @@ -9,13 +9,25 @@ steps: sudo service xvfb start - task: NodeTool@0 inputs: - versionSpec: "8.12.0" + versionSpec: "10.15.1" +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: '$(ArtifactFeed)' - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: versionSpec: "1.10.1" - script: | - yarn + yarn --frozen-lockfile displayName: Install Dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) +- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: '$(ArtifactFeed)' + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - script: | yarn gulp electron-x64 displayName: Download Electron @@ -25,9 +37,6 @@ steps: - script: | yarn monaco-compile-check displayName: Run Monaco Editor Checks -- script: | - yarn strict-null-check - displayName: Run Strict Null Checks - script: | yarn compile displayName: Compile Sources @@ -37,9 +46,12 @@ steps: - script: | DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests" displayName: Run Unit Tests +- script: | + DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests" + displayName: Run Integration Tests - task: PublishTestResults@2 displayName: Publish Tests Results inputs: testResultsFiles: '*-results.xml' searchFolder: '$(Build.ArtifactStagingDirectory)/test-results' - condition: succeededOrFailed() \ No newline at end of file + condition: succeededOrFailed() diff --git a/build/azure-pipelines/linux/multiarch/alpine/build.sh b/build/azure-pipelines/linux/multiarch/alpine/build.sh new file mode 100755 index 00000000000..4f01bc9a7e5 --- /dev/null +++ b/build/azure-pipelines/linux/multiarch/alpine/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +echo 'noop' \ No newline at end of file diff --git a/build/azure-pipelines/linux/multiarch/alpine/prebuild.sh b/build/azure-pipelines/linux/multiarch/alpine/prebuild.sh new file mode 100755 index 00000000000..4f01bc9a7e5 --- /dev/null +++ b/build/azure-pipelines/linux/multiarch/alpine/prebuild.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +echo 'noop' \ No newline at end of file diff --git a/build/azure-pipelines/linux/multiarch/alpine/publish.sh b/build/azure-pipelines/linux/multiarch/alpine/publish.sh new file mode 100755 index 00000000000..4f01bc9a7e5 --- /dev/null +++ b/build/azure-pipelines/linux/multiarch/alpine/publish.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +echo 'noop' \ No newline at end of file diff --git a/build/azure-pipelines/linux/multiarch/arm64/build.sh b/build/azure-pipelines/linux/multiarch/arm64/build.sh new file mode 100755 index 00000000000..4f01bc9a7e5 --- /dev/null +++ b/build/azure-pipelines/linux/multiarch/arm64/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +echo 'noop' \ No newline at end of file diff --git a/build/azure-pipelines/linux/multiarch/arm64/prebuild.sh b/build/azure-pipelines/linux/multiarch/arm64/prebuild.sh new file mode 100755 index 00000000000..4f01bc9a7e5 --- /dev/null +++ b/build/azure-pipelines/linux/multiarch/arm64/prebuild.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +echo 'noop' \ No newline at end of file diff --git a/build/azure-pipelines/linux/multiarch/arm64/publish.sh b/build/azure-pipelines/linux/multiarch/arm64/publish.sh new file mode 100755 index 00000000000..4f01bc9a7e5 --- /dev/null +++ b/build/azure-pipelines/linux/multiarch/arm64/publish.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +echo 'noop' \ No newline at end of file diff --git a/build/azure-pipelines/linux/multiarch/armhf/build.sh b/build/azure-pipelines/linux/multiarch/armhf/build.sh new file mode 100755 index 00000000000..4f01bc9a7e5 --- /dev/null +++ b/build/azure-pipelines/linux/multiarch/armhf/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +echo 'noop' \ No newline at end of file diff --git a/build/azure-pipelines/linux/multiarch/armhf/prebuild.sh b/build/azure-pipelines/linux/multiarch/armhf/prebuild.sh new file mode 100755 index 00000000000..4f01bc9a7e5 --- /dev/null +++ b/build/azure-pipelines/linux/multiarch/armhf/prebuild.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +echo 'noop' \ No newline at end of file diff --git a/build/azure-pipelines/linux/multiarch/armhf/publish.sh b/build/azure-pipelines/linux/multiarch/armhf/publish.sh new file mode 100755 index 00000000000..4f01bc9a7e5 --- /dev/null +++ b/build/azure-pipelines/linux/multiarch/armhf/publish.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +echo 'noop' \ No newline at end of file diff --git a/build/azure-pipelines/linux/product-build-linux-multiarch.yml b/build/azure-pipelines/linux/product-build-linux-multiarch.yml new file mode 100644 index 00000000000..dff5ae2ceaf --- /dev/null +++ b/build/azure-pipelines/linux/product-build-linux-multiarch.yml @@ -0,0 +1,115 @@ +steps: +- script: | + mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + displayName: Prepare cache flag + +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: 'build/.cachesalt, .build/commit' + targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' + vstsFeed: 'npm-vscode' + platformIndependent: true + alias: 'Compilation' + +- script: | + set -e + exit 1 + displayName: Check RestoreCache + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- task: NodeTool@0 + inputs: + versionSpec: "10.15.1" + +- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.10.1" + +- task: AzureKeyVault@1 + displayName: 'Azure Key Vault: Get Secrets' + inputs: + azureSubscription: 'vscode-builds-subscription' + KeyVaultName: vscode + +- task: Docker@1 + displayName: 'Pull image' + inputs: + azureSubscriptionEndpoint: 'vscode-builds-subscription' + azureContainerRegistry: vscodehub.azurecr.io + command: 'Run an image' + imageName: 'vscode-linux-build-agent:$(VSCODE_ARCH)' + containerCommand: uname + +- script: | + set -e + + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF + + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling + +- script: | + set -e + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro + +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: 'npm-vscode' + +- script: | + set -e + CHILD_CONCURRENCY=1 yarn --frozen-lockfile + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + +- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: 'npm-vscode' + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + +- script: | + set -e + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + +- script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality + +- script: | + set -e + CHILD_CONCURRENCY=1 ./build/azure-pipelines/linux/multiarch/$(VSCODE_ARCH)/prebuild.sh + displayName: Prebuild + +- script: | + set -e + ./build/azure-pipelines/linux/multiarch/$(VSCODE_ARCH)/build.sh + displayName: Build + +- script: | + set -e + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + VSCODE_HOCKEYAPP_TOKEN="$(vscode-hockeyapp-token)" \ + ./build/azure-pipelines/linux/multiarch/$(VSCODE_ARCH)/publish.sh + displayName: Publish + +- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: 'Component Detection' + continueOnError: true \ No newline at end of file diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 6cf126af1e4..dee07a95d78 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -1,112 +1,130 @@ steps: +- script: | + mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + displayName: Prepare cache flag + +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: 'build/.cachesalt, .build/commit' + targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' + vstsFeed: 'npm-vscode' + platformIndependent: true + alias: 'Compilation' + +- script: | + set -e + exit 1 + displayName: Check RestoreCache + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + - task: NodeTool@0 inputs: - versionSpec: "8.12.0" + versionSpec: "10.15.1" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: versionSpec: "1.10.1" -- script: | - set -e - export npm_config_arch="$(VSCODE_ARCH)" - if [[ "$(VSCODE_ARCH)" == "ia32" ]]; then - export PKG_CONFIG_PATH="/usr/lib/i386-linux-gnu/pkgconfig" - fi - - echo "machine monacotools.visualstudio.com password $(VSO_PAT)" > ~/.netrc - CHILD_CONCURRENCY=1 yarn - npm run gulp -- hygiene - npm run monaco-compile-check - npm run strict-null-check - VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin - node build/azure-pipelines/common/installDistro.js - node build/lib/builtInExtensions.js +- task: AzureKeyVault@1 + displayName: 'Azure Key Vault: Get Secrets' + inputs: + azureSubscription: 'vscode-builds-subscription' + KeyVaultName: vscode - script: | set -e - VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- vscode-linux-$(VSCODE_ARCH)-min - name: build + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF + + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling - script: | set -e - npm run gulp -- "electron-$(VSCODE_ARCH)" + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro - # xvfb seems to be crashing often, let's make sure it's always up +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: 'npm-vscode' + +- script: | + set -e + CHILD_CONCURRENCY=1 yarn --frozen-lockfile + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + +- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: 'npm-vscode' + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + +- script: | + set -e + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + +- script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality + +- script: | + set -e + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-linux-x64-min-ci + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-reh-linux-x64-min-ci + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-reh-web-linux-x64-min-ci + displayName: Build + +- script: | + set -e service xvfb start - - DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" - # yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)" - name: test + displayName: Start xvfb + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - script: | set -e - REPO="$(pwd)" - ROOT="$REPO/.." - ARCH="$(VSCODE_ARCH)" + DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" + displayName: Run unit tests + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - # Publish tarball - PLATFORM_LINUX="linux-$(VSCODE_ARCH)" - [[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64" - [[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64" - BUILDNAME="VSCode-$PLATFORM_LINUX" - BUILD="$ROOT/$BUILDNAME" - BUILD_VERSION="$(date +%s)" - [ -z "$VSCODE_QUALITY" ] && TARBALL_FILENAME="code-$BUILD_VERSION.tar.gz" || TARBALL_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.tar.gz" - TARBALL_PATH="$ROOT/$TARBALL_FILENAME" - PACKAGEJSON="$BUILD/resources/app/package.json" - VERSION=$(node -p "require(\"$PACKAGEJSON\").version") +- script: | + set -e + DISPLAY=:10 ./scripts/test-integration.sh --build --tfs "Integration Tests" + # yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-x64" + displayName: Run integration tests + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - rm -rf $ROOT/code-*.tar.* - (cd $ROOT && tar -czf $TARBALL_PATH $BUILDNAME) - - AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ - AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \ - MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \ - node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH" - - # Publish hockeyapp symbols - node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_LINUX64)" - - # Publish DEB - npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-deb" - PLATFORM_DEB="linux-deb-$ARCH" - [[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64" - DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)" - DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME" - - AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ - AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \ - MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \ - node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_DEB" package "$DEB_FILENAME" "$VERSION" true "$DEB_PATH" - - # Publish RPM - npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-rpm" - PLATFORM_RPM="linux-rpm-$ARCH" - [[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64" - RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)" - RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME" - - AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ - AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \ - MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \ - node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_RPM" package "$RPM_FILENAME" "$VERSION" true "$RPM_PATH" - - # Publish Snap - npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-prepare-snap" - - # Pack snap tarball artifact, in order to preserve file perms - mkdir -p $REPO/.build/linux/snap-tarball - SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$(VSCODE_ARCH).tar.gz" - rm -rf $SNAP_TARBALL_PATH - (cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap) - -- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' - continueOnError: true +- script: | + set -e + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + VSCODE_HOCKEYAPP_TOKEN="$(vscode-hockeyapp-token)" \ + ./build/azure-pipelines/linux/publish.sh + displayName: Publish - task: PublishPipelineArtifact@0 displayName: 'Publish Pipeline Artifact' inputs: - artifactName: snap-$(VSCODE_ARCH) + artifactName: snap-x64 targetPath: .build/linux/snap-tarball + +- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: 'Component Detection' + continueOnError: true diff --git a/build/azure-pipelines/linux/publish.sh b/build/azure-pipelines/linux/publish.sh new file mode 100755 index 00000000000..5fc86d02d60 --- /dev/null +++ b/build/azure-pipelines/linux/publish.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +set -e +REPO="$(pwd)" +ROOT="$REPO/.." + +# Publish tarball +PLATFORM_LINUX="linux-x64" +BUILDNAME="VSCode-$PLATFORM_LINUX" +BUILD="$ROOT/$BUILDNAME" +BUILD_VERSION="$(date +%s)" +[ -z "$VSCODE_QUALITY" ] && TARBALL_FILENAME="code-$BUILD_VERSION.tar.gz" || TARBALL_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.tar.gz" +TARBALL_PATH="$ROOT/$TARBALL_FILENAME" +PACKAGEJSON="$BUILD/resources/app/package.json" +VERSION=$(node -p "require(\"$PACKAGEJSON\").version") + +rm -rf $ROOT/code-*.tar.* +(cd $ROOT && tar -czf $TARBALL_PATH $BUILDNAME) + +node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH" + +# Publish Remote Extension Host +LEGACY_SERVER_BUILD_NAME="vscode-reh-$PLATFORM_LINUX" +SERVER_BUILD_NAME="vscode-server-$PLATFORM_LINUX" +SERVER_TARBALL_FILENAME="vscode-server-$PLATFORM_LINUX.tar.gz" +SERVER_TARBALL_PATH="$ROOT/$SERVER_TARBALL_FILENAME" + +rm -rf $ROOT/vscode-server-*.tar.* +(cd $ROOT && mv $LEGACY_SERVER_BUILD_NAME $SERVER_BUILD_NAME && tar --owner=0 --group=0 -czf $SERVER_TARBALL_PATH $SERVER_BUILD_NAME) + +node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "server-$PLATFORM_LINUX" archive-unsigned "$SERVER_TARBALL_FILENAME" "$VERSION" true "$SERVER_TARBALL_PATH" + +# Publish hockeyapp symbols +node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "x64" "$VSCODE_HOCKEYAPP_ID_LINUX64" + +# Publish DEB +yarn gulp "vscode-linux-x64-build-deb" +PLATFORM_DEB="linux-deb-x64" +DEB_ARCH="amd64" +DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)" +DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME" + +node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_DEB" package "$DEB_FILENAME" "$VERSION" true "$DEB_PATH" + +# Publish RPM +yarn gulp "vscode-linux-x64-build-rpm" +PLATFORM_RPM="linux-rpm-x64" +RPM_ARCH="x86_64" +RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)" +RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME" + +node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_RPM" package "$RPM_FILENAME" "$VERSION" true "$RPM_PATH" + +# Publish Snap +yarn gulp "vscode-linux-x64-prepare-snap" + +# Pack snap tarball artifact, in order to preserve file perms +mkdir -p $REPO/.build/linux/snap-tarball +SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-x64.tar.gz" +rm -rf $SNAP_TARBALL_PATH +(cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap) diff --git a/build/azure-pipelines/linux/snap-build-linux.yml b/build/azure-pipelines/linux/snap-build-linux.yml index 29252107f46..4c3f602e8ce 100644 --- a/build/azure-pipelines/linux/snap-build-linux.yml +++ b/build/azure-pipelines/linux/snap-build-linux.yml @@ -1,30 +1,43 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "8.12.0" + versionSpec: "10.15.1" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: versionSpec: "1.10.1" +- task: AzureKeyVault@1 + displayName: 'Azure Key Vault: Get Secrets' + inputs: + azureSubscription: 'vscode-builds-subscription' + KeyVaultName: vscode + - task: DownloadPipelineArtifact@0 displayName: 'Download Pipeline Artifact' inputs: - artifactName: snap-$(VSCODE_ARCH) + artifactName: snap-x64 targetPath: .build/linux/snap-tarball - script: | set -e + # Get snapcraft version + snapcraft --version + + # Make sure we get latest packages + sudo apt-get update + sudo apt-get upgrade -y + + # Define variables REPO="$(pwd)" - ARCH="$(VSCODE_ARCH)" - SNAP_ROOT="$REPO/.build/linux/snap/$ARCH" + SNAP_ROOT="$REPO/.build/linux/snap/x64" # Install build dependencies (cd build && yarn) # Unpack snap tarball artifact, in order to preserve file perms - SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$ARCH.tar.gz" + SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-x64.tar.gz" (cd .build/linux && tar -xzf $SNAP_TARBALL_PATH) # Create snap package @@ -33,10 +46,9 @@ steps: PACKAGEJSON="$(ls $SNAP_ROOT/code*/usr/share/code*/resources/app/package.json)" VERSION=$(node -p "require(\"$PACKAGEJSON\").version") SNAP_PATH="$SNAP_ROOT/$SNAP_FILENAME" - (cd $SNAP_ROOT/code-* && snapcraft snap --output "$SNAP_PATH") + (cd $SNAP_ROOT/code-* && sudo --preserve-env snapcraft snap --output "$SNAP_PATH") # Publish snap package - AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ - AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \ - MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \ - node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "linux-snap-$ARCH" package "$SNAP_FILENAME" "$VERSION" true "$SNAP_PATH" \ No newline at end of file + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "linux-snap-x64" package "$SNAP_FILENAME" "$VERSION" true "$SNAP_PATH" \ No newline at end of file diff --git a/build/azure-pipelines/mixin.js b/build/azure-pipelines/mixin.js new file mode 100644 index 00000000000..efb7d4d1ca9 --- /dev/null +++ b/build/azure-pipelines/mixin.js @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +const json = require('gulp-json-editor'); +const buffer = require('gulp-buffer'); +const filter = require('gulp-filter'); +const es = require('event-stream'); +const vfs = require('vinyl-fs'); +const fancyLog = require('fancy-log'); +const ansiColors = require('ansi-colors'); + +function main() { + const quality = process.env['VSCODE_QUALITY']; + + if (!quality) { + console.log('Missing VSCODE_QUALITY, skipping mixin'); + return; + } + + const productJsonFilter = filter('product.json', { restore: true }); + + fancyLog(ansiColors.blue('[mixin]'), `Mixing in sources:`); + return vfs + .src(`quality/${quality}/**`, { base: `quality/${quality}` }) + .pipe(filter(f => !f.isDirectory())) + .pipe(productJsonFilter) + .pipe(buffer()) + .pipe(json(o => Object.assign({}, require('../product.json'), o))) + .pipe(productJsonFilter.restore) + .pipe(es.mapSync(function (f) { + fancyLog(ansiColors.blue('[mixin]'), f.relative, ansiColors.green('✔︎')); + return f; + })) + .pipe(vfs.dest('.')); +} + +main(); \ No newline at end of file diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index afebc973ccc..f38f4311826 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -1,65 +1,150 @@ resources: containers: - container: vscode-x64 - image: joaomoreno/vscode-linux-build-agent:x64 - - container: vscode-ia32 - image: joaomoreno/vscode-linux-build-agent:ia32 + image: vscodehub.azurecr.io/vscode-linux-build-agent:x64 + endpoint: VSCodeHub - container: snapcraft - image: snapcore/snapcraft + image: snapcore/snapcraft:stable jobs: +- job: Compile + pool: + vmImage: 'Ubuntu-16.04' + container: vscode-x64 + steps: + - template: product-compile.yml + - job: Windows - condition: eq(variables['VSCODE_BUILD_WIN32'], 'true') + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_WIN32'], 'true')) pool: vmImage: VS2017-Win2016 variables: VSCODE_ARCH: x64 + dependsOn: + - Compile steps: - template: win32/product-build-win32.yml - job: Windows32 - condition: eq(variables['VSCODE_BUILD_WIN32_32BIT'], 'true') + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_WIN32_32BIT'], 'true')) pool: vmImage: VS2017-Win2016 variables: VSCODE_ARCH: ia32 + dependsOn: + - Compile steps: - template: win32/product-build-win32.yml - job: Linux - condition: eq(variables['VSCODE_BUILD_LINUX'], 'true') + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX'], 'true')) pool: vmImage: 'Ubuntu-16.04' - variables: - VSCODE_ARCH: x64 container: vscode-x64 + dependsOn: + - Compile steps: - template: linux/product-build-linux.yml - job: LinuxSnap - condition: eq(variables['VSCODE_BUILD_LINUX'], 'true') + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX'], 'true')) pool: vmImage: 'Ubuntu-16.04' - variables: - VSCODE_ARCH: x64 container: snapcraft dependsOn: Linux steps: - template: linux/snap-build-linux.yml -- job: Linux32 - condition: eq(variables['VSCODE_BUILD_LINUX_32BIT'], 'true') +- job: LinuxArmhf + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true'), ne(variables['VSCODE_QUALITY'], 'stable')) pool: vmImage: 'Ubuntu-16.04' variables: - VSCODE_ARCH: ia32 - container: vscode-ia32 + VSCODE_ARCH: armhf + dependsOn: + - Compile steps: - - template: linux/product-build-linux.yml + - template: linux/product-build-linux-multiarch.yml + +- job: LinuxArm64 + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX_ARM64'], 'true'), ne(variables['VSCODE_QUALITY'], 'stable')) + pool: + vmImage: 'Ubuntu-16.04' + variables: + VSCODE_ARCH: arm64 + dependsOn: + - Compile + steps: + - template: linux/product-build-linux-multiarch.yml + +- job: LinuxAlpine + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX_ALPINE'], 'true'), ne(variables['VSCODE_QUALITY'], 'stable')) + pool: + vmImage: 'Ubuntu-16.04' + variables: + VSCODE_ARCH: alpine + dependsOn: + - Compile + steps: + - template: linux/product-build-linux-multiarch.yml + +- job: LinuxWeb + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_WEB'], 'true')) + pool: + vmImage: 'Ubuntu-16.04' + variables: + VSCODE_ARCH: x64 + dependsOn: + - Compile + steps: + - template: web/product-build-web.yml - job: macOS - condition: eq(variables['VSCODE_BUILD_MACOS'], 'true') + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_MACOS'], 'true')) pool: vmImage: macOS 10.13 + dependsOn: + - Compile steps: - - template: darwin/product-build-darwin.yml \ No newline at end of file + - template: darwin/product-build-darwin.yml + +- job: Release + condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), or(eq(variables['VSCODE_RELEASE'], 'true'), and(or(eq(variables['VSCODE_QUALITY'], 'insider'), eq(variables['VSCODE_QUALITY'], 'exploration')), eq(variables['Build.Reason'], 'Schedule')))) + pool: + vmImage: 'Ubuntu-16.04' + dependsOn: + - Windows + - Windows32 + - Linux + - LinuxSnap + - LinuxArmhf + - LinuxAlpine + - macOS + steps: + - template: release.yml + +- job: Mooncake + pool: + vmImage: 'Ubuntu-16.04' + condition: and(succeededOrFailed(), eq(variables['VSCODE_COMPILE_ONLY'], 'false')) + dependsOn: + - Windows + - Windows32 + - Linux + - LinuxSnap + - LinuxArmhf + - LinuxAlpine + - LinuxWeb + - macOS + steps: + - template: sync-mooncake.yml + +trigger: none +pr: none + +schedules: +- cron: "0 5 * * Mon-Fri" + displayName: Mon-Fri at 7:00 + branches: + include: + - master diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml new file mode 100644 index 00000000000..e5105326e7b --- /dev/null +++ b/build/azure-pipelines/product-compile.yml @@ -0,0 +1,124 @@ +steps: +- script: | + mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + displayName: Prepare cache flag + +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: 'build/.cachesalt, .build/commit' + targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' + vstsFeed: 'npm-vscode' + platformIndependent: true + alias: 'Compilation' + +- task: NodeTool@0 + inputs: + versionSpec: "10.15.1" + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.10.1" + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- task: AzureKeyVault@1 + displayName: 'Azure Key Vault: Get Secrets' + inputs: + azureSubscription: 'vscode-builds-subscription' + KeyVaultName: vscode + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- script: | + set -e + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF + + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- script: | + set -e + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: 'npm-vscode' + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- script: | + set -e + CHILD_CONCURRENCY=1 yarn --frozen-lockfile + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) + +- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: 'npm-vscode' + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) + +- script: | + set -e + yarn postinstall + displayName: Run postinstall scripts + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'), eq(variables['CacheRestored'], 'true')) + +# Mixin must run before optimize, because the CSS loader will +# inline small SVGs +- script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- script: | + set -e + yarn gulp hygiene + yarn monaco-compile-check + displayName: Run hygiene checks + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + +- script: | + set - + ./build/azure-pipelines/common/extract-telemetry.sh + displayName: Extract Telemetry + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- script: | + set -e + yarn gulp compile-build + yarn gulp compile-extensions-build + yarn gulp minify-vscode + yarn gulp minify-vscode-reh + yarn gulp minify-vscode-reh-web + displayName: Compile + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- script: | + set -e + AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ + node build/azure-pipelines/upload-sourcemaps + displayName: Upload sourcemaps + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: 'build/.cachesalt, .build/commit' + targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' + vstsFeed: 'npm-vscode' + platformIndependent: true + alias: 'Compilation' + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) \ No newline at end of file diff --git a/build/azure-pipelines/publish-types/.gitignore b/build/azure-pipelines/publish-types/.gitignore new file mode 100644 index 00000000000..e94ecda764e --- /dev/null +++ b/build/azure-pipelines/publish-types/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +*.js \ No newline at end of file diff --git a/build/azure-pipelines/publish-types/check-version.ts b/build/azure-pipelines/publish-types/check-version.ts new file mode 100644 index 00000000000..2c730889112 --- /dev/null +++ b/build/azure-pipelines/publish-types/check-version.ts @@ -0,0 +1,43 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as cp from 'child_process'; + +let tag = ''; +try { + tag = cp + .execSync('git describe --tags `git rev-list --tags --max-count=1`') + .toString() + .trim(); + + if (!isValidTag(tag)) { + throw Error(`Invalid tag ${tag}`); + } +} catch (err) { + console.error(err); + console.error('Failed to update types'); + process.exit(1); +} + +function isValidTag(t: string) { + if (t.split('.').length !== 3) { + return false; + } + + const [major, minor, bug] = t.split('.'); + + // Only release for tags like 1.34.0 + if (bug !== '0') { + return false; + } + + if (parseInt(major, 10) === NaN || parseInt(minor, 10) === NaN) { + return false; + } + + return true; +} \ No newline at end of file diff --git a/build/azure-pipelines/publish-types/publish-types.yml b/build/azure-pipelines/publish-types/publish-types.yml new file mode 100644 index 00000000000..ff03cecedb1 --- /dev/null +++ b/build/azure-pipelines/publish-types/publish-types.yml @@ -0,0 +1,67 @@ +# Publish @types/vscode for each release + +trigger: + branches: + include: ['refs/tags/*'] + +pr: none + +steps: +- task: NodeTool@0 + inputs: + versionSpec: "10.15.1" + +- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.10.1" + +- bash: | + # Install build dependencies + (cd build && yarn) + node build/azure-pipelines/publish-types/check-version.js + displayName: Check version + +- bash: | + git config --global user.email "vscode@microsoft.com" + git config --global user.name "VSCode" + + git clone https://$(GITHUB_TOKEN)@github.com/DefinitelyTyped/DefinitelyTyped.git --depth=1 + node build/azure-pipelines/publish-types/update-types.js + + TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`) + + cd DefinitelyTyped + + git diff --color | cat + git add -A + git status + git checkout -b "vscode-types-$TAG_VERSION" + git commit -m "VS Code $TAG_VERSION Extension API" + git push origin "vscode-types-$TAG_VERSION" + + displayName: Push update to DefinitelyTyped + +- bash: | + TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`) + CHANNEL="G1C14HJ2F" + + MESSAGE="DefinitelyTyped/DefinitelyTyped#vscode-types-$TAG_VERSION created. Endgame master, please open this link, examine changes and create a PR:" + LINK="https://github.com/DefinitelyTyped/DefinitelyTyped/compare/vscode-types-$TAG_VERSION?quick_pull=1&body=Updating%20VS%20Code%20Extension%20API.%20See%20https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fvscode%2Fissues%2F70175%20for%20details." + MESSAGE2="[@octref, @jrieken, @kmaetzel, @egamma]. Please review and merge PR to publish @types/vscode." + + curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \ + -H 'Content-type: application/json; charset=utf-8' \ + --data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE"'"}' \ + https://slack.com/api/chat.postMessage + + curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \ + -H 'Content-type: application/json; charset=utf-8' \ + --data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$LINK"'"}' \ + https://slack.com/api/chat.postMessage + + curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \ + -H 'Content-type: application/json; charset=utf-8' \ + --data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE2"'"}' \ + https://slack.com/api/chat.postMessage + + displayName: Send message on Slack diff --git a/build/azure-pipelines/publish-types/update-types.ts b/build/azure-pipelines/publish-types/update-types.ts new file mode 100644 index 00000000000..a5ef449b77b --- /dev/null +++ b/build/azure-pipelines/publish-types/update-types.ts @@ -0,0 +1,73 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as fs from 'fs'; +import * as cp from 'child_process'; +import * as path from 'path'; + +let tag = ''; +try { + tag = cp + .execSync('git describe --tags `git rev-list --tags --max-count=1`') + .toString() + .trim(); + + const dtsUri = `https://raw.githubusercontent.com/microsoft/vscode/${tag}/src/vs/vscode.d.ts`; + const outPath = path.resolve(process.cwd(), 'DefinitelyTyped/types/vscode/index.d.ts'); + cp.execSync(`curl ${dtsUri} --output ${outPath}`); + + updateDTSFile(outPath, tag); + + console.log(`Done updating vscode.d.ts at ${outPath}`); +} catch (err) { + console.error(err); + console.error('Failed to update types'); + process.exit(1); +} + +function updateDTSFile(outPath: string, tag: string) { + const oldContent = fs.readFileSync(outPath, 'utf-8'); + const newContent = getNewFileContent(oldContent, tag); + + fs.writeFileSync(outPath, newContent); +} + +function getNewFileContent(content: string, tag: string) { + const oldheader = [ + `/*---------------------------------------------------------------------------------------------`, + ` * Copyright (c) Microsoft Corporation. All rights reserved.`, + ` * Licensed under the MIT License. See License.txt in the project root for license information.`, + ` *--------------------------------------------------------------------------------------------*/` + ].join('\n'); + + return getNewFileHeader(tag) + content.slice(oldheader.length); +} + +function getNewFileHeader(tag: string) { + const [major, minor] = tag.split('.'); + const shorttag = `${major}.${minor}`; + + const header = [ + `// Type definitions for Visual Studio Code ${shorttag}`, + `// Project: https://github.com/microsoft/vscode`, + `// Definitions by: Visual Studio Code Team, Microsoft `, + `// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped`, + ``, + `/*---------------------------------------------------------------------------------------------`, + ` * Copyright (c) Microsoft Corporation. All rights reserved.`, + ` * Licensed under the MIT License.`, + ` * See https://github.com/Microsoft/vscode/blob/master/LICENSE.txt for license information.`, + ` *--------------------------------------------------------------------------------------------*/`, + ``, + `/**`, + ` * Type Definition for Visual Studio Code ${shorttag} Extension API`, + ` * See https://code.visualstudio.com/api for more information`, + ` */` + ].join('\n'); + + return header; +} diff --git a/build/azure-pipelines/release.yml b/build/azure-pipelines/release.yml new file mode 100644 index 00000000000..eee54a1d8b7 --- /dev/null +++ b/build/azure-pipelines/release.yml @@ -0,0 +1,22 @@ +steps: +- task: NodeTool@0 + inputs: + versionSpec: "10.x" + +- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.x" + +- task: AzureKeyVault@1 + displayName: 'Azure Key Vault: Get Secrets' + inputs: + azureSubscription: 'vscode-builds-subscription' + KeyVaultName: vscode + +- script: | + set -e + + (cd build ; yarn) + + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + node build/azure-pipelines/common/release.js diff --git a/build/azure-pipelines/sync-mooncake.yml b/build/azure-pipelines/sync-mooncake.yml new file mode 100644 index 00000000000..f3e8bc07856 --- /dev/null +++ b/build/azure-pipelines/sync-mooncake.yml @@ -0,0 +1,24 @@ +steps: +- task: NodeTool@0 + inputs: + versionSpec: "10.15.1" + +- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.10.1" + +- task: AzureKeyVault@1 + displayName: 'Azure Key Vault: Get Secrets' + inputs: + azureSubscription: 'vscode-builds-subscription' + KeyVaultName: vscode + +- script: | + set -e + + (cd build ; yarn) + + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + MOONCAKE_STORAGE_ACCESS_KEY="$(vscode-mooncake-storage-key)" \ + node build/azure-pipelines/common/sync-mooncake.js "$VSCODE_QUALITY" diff --git a/build/azure-pipelines/upload-sourcemaps.js b/build/azure-pipelines/upload-sourcemaps.js new file mode 100644 index 00000000000..ac3bd55a7f5 --- /dev/null +++ b/build/azure-pipelines/upload-sourcemaps.js @@ -0,0 +1,39 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +const path = require('path'); +const es = require('event-stream'); +const azure = require('gulp-azure-storage'); +const vfs = require('vinyl-fs'); +const util = require('../lib/util'); +const root = path.dirname(path.dirname(__dirname)); +const commit = util.getVersion(root); + +function main() { + const vs = vfs.src('out-vscode-min/**/*.map', { base: 'out-vscode-min' }) // client source-maps only + .pipe(es.mapSync(f => { + f.path = `${f.base}/core/${f.relative}`; + return f; + })); + + const extensionsOut = vfs.src(['.build/extensions/**/*.js.map', '!**/node_modules/**'], { base: '.build' }); + + return es.merge(vs, extensionsOut) + .pipe(es.through(function (data) { + // debug + console.log('Uploading Sourcemap', data.relative); + this.emit('data', data); + })) + .pipe(azure.upload({ + account: process.env.AZURE_STORAGE_ACCOUNT, + key: process.env.AZURE_STORAGE_ACCESS_KEY, + container: 'sourcemaps', + prefix: commit + '/' + })); +} + +main(); \ No newline at end of file diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml new file mode 100644 index 00000000000..7c65dc982f0 --- /dev/null +++ b/build/azure-pipelines/web/product-build-web.yml @@ -0,0 +1,96 @@ +steps: +- script: | + mkdir -p .build + echo -n $BUILD_SOURCEVERSION > .build/commit + displayName: Prepare cache flag + +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: 'build/.cachesalt, .build/commit' + targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' + vstsFeed: 'npm-vscode' + platformIndependent: true + alias: 'Compilation' + +- script: | + set -e + exit 1 + displayName: Check RestoreCache + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + +- task: NodeTool@0 + inputs: + versionSpec: "10.15.1" + +- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.10.1" + +- task: AzureKeyVault@1 + displayName: 'Azure Key Vault: Get Secrets' + inputs: + azureSubscription: 'vscode-builds-subscription' + KeyVaultName: vscode + +- script: | + set -e + cat << EOF > ~/.netrc + machine github.com + login vscode + password $(github-distro-mixin-password) + EOF + + git config user.email "vscode@microsoft.com" + git config user.name "VSCode" + displayName: Prepare tooling + +- script: | + set -e + git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" + git fetch distro + git merge $(node -p "require('./package.json').distro") + displayName: Merge distro + +# - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 +# inputs: +# keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' +# targetfolder: '**/node_modules, !**/node_modules/**/node_modules' +# vstsFeed: 'npm-vscode' + +- script: | + set -e + CHILD_CONCURRENCY=1 yarn --frozen-lockfile + displayName: Install dependencies + # condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + +# - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 +# inputs: +# keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' +# targetfolder: '**/node_modules, !**/node_modules/**/node_modules' +# vstsFeed: 'npm-vscode' +# condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + +# - script: | +# set -e +# yarn postinstall +# displayName: Run postinstall scripts +# condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + +- script: | + set -e + node build/azure-pipelines/mixin + displayName: Mix in quality + +- script: | + set -e + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + yarn gulp vscode-web-min-ci + displayName: Build + +- script: | + set -e + AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ + AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ + VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ + ./build/azure-pipelines/web/publish.sh + displayName: Publish diff --git a/build/azure-pipelines/web/publish.sh b/build/azure-pipelines/web/publish.sh new file mode 100755 index 00000000000..2c112362a25 --- /dev/null +++ b/build/azure-pipelines/web/publish.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -e +REPO="$(pwd)" +ROOT="$REPO/.." + +# Publish Web Client +WEB_BUILD_NAME="vscode-web" +WEB_TARBALL_FILENAME="vscode-web.tar.gz" +WEB_TARBALL_PATH="$ROOT/$WEB_TARBALL_FILENAME" +BUILD="$ROOT/$WEB_BUILD_NAME" +PACKAGEJSON="$BUILD/package.json" +VERSION=$(node -p "require(\"$PACKAGEJSON\").version") + +rm -rf $ROOT/vscode-web.tar.* + +(cd $ROOT && tar --owner=0 --group=0 -czf $WEB_TARBALL_PATH $WEB_BUILD_NAME) + +node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "web-standalone" archive-unsigned "$WEB_TARBALL_FILENAME" "$VERSION" true "$WEB_TARBALL_PATH" diff --git a/build/azure-pipelines/win32/continuous-build-win32.yml b/build/azure-pipelines/win32/continuous-build-win32.yml index 7145e67e2ad..9b6d61ee974 100644 --- a/build/azure-pipelines/win32/continuous-build-win32.yml +++ b/build/azure-pipelines/win32/continuous-build-win32.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "8.12.0" + versionSpec: "10.15.1" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: versionSpec: "1.10.1" @@ -9,9 +9,21 @@ steps: inputs: versionSpec: '2.x' addToPath: true +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: '$(ArtifactFeed)' - powershell: | - yarn + yarn --frozen-lockfile displayName: Install Dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) +- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: '.yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: '$(ArtifactFeed)' + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - powershell: | yarn gulp electron displayName: Download Electron @@ -21,9 +33,6 @@ steps: - powershell: | yarn monaco-compile-check displayName: Run Monaco Editor Checks -- script: | - yarn strict-null-check - displayName: Run Strict Null Checks - powershell: | yarn compile displayName: Compile Sources diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 418af9e10a9..7a72dcfb09b 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -1,7 +1,26 @@ steps: +- powershell: | + mkdir .build -ea 0 + "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit + displayName: Prepare cache flag + +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: 'build/.cachesalt, .build/commit' + targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' + vstsFeed: 'npm-vscode' + platformIndependent: true + alias: 'Compilation' + +- powershell: | + $ErrorActionPreference = "Stop" + exit 1 + displayName: Check RestoreCache + condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) + - task: NodeTool@0 inputs: - versionSpec: "8.12.0" + versionSpec: "10.15.1" - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 inputs: @@ -12,41 +31,98 @@ steps: versionSpec: '2.x' addToPath: true +- task: AzureKeyVault@1 + displayName: 'Azure Key Vault: Get Secrets' + inputs: + azureSubscription: 'vscode-builds-subscription' + KeyVaultName: vscode + +- powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + "machine github.com`nlogin vscode`npassword $(github-distro-mixin-password)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII + + exec { git config user.email "vscode@microsoft.com" } + exec { git config user.name "VSCode" } + + mkdir .build -ea 0 + "$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch + displayName: Prepare tooling + +- powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" } + exec { git fetch distro } + exec { git merge $(node -p "require('./package.json').distro") } + displayName: Merge distro + +- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 + inputs: + keyfile: 'build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: 'npm-vscode' + - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" - "machine monacotools.visualstudio.com password $(VSO_PAT)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII $env:npm_config_arch="$(VSCODE_ARCH)" $env:CHILD_CONCURRENCY="1" - $env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" - exec { yarn } - exec { npm run gulp -- hygiene } - exec { npm run monaco-compile-check } - exec { npm run strict-null-check } - exec { npm run gulp -- mixin } - exec { node build/azure-pipelines/common/installDistro.js } - exec { node build/lib/builtInExtensions.js } + exec { yarn --frozen-lockfile } + displayName: Install dependencies + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) + +- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 + inputs: + keyfile: 'build/.cachesalt, .build/arch, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock' + targetfolder: '**/node_modules, !**/node_modules/**/node_modules' + vstsFeed: 'npm-vscode' + condition: and(succeeded(), ne(variables['CacheRestored'], 'true')) - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" - $env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" - exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-min" } - exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-inno-updater" } - name: build + exec { yarn postinstall } + displayName: Run postinstall scripts + condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" - exec { npm run gulp -- "electron-$(VSCODE_ARCH)" } + exec { node build/azure-pipelines/mixin } + displayName: Mix in quality + +- powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" + exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" } + exec { yarn gulp "vscode-reh-win32-$env:VSCODE_ARCH-min-ci" } + exec { yarn gulp "vscode-reh-web-win32-$env:VSCODE_ARCH-min-ci" } + exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-code-helper" } + exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" } + displayName: Build + +- powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { yarn gulp "electron-$(VSCODE_ARCH)" } exec { .\scripts\test.bat --build --tfs "Unit Tests" } - # yarn smoketest -- --build "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)" - name: test + displayName: Run unit tests + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + +- powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + exec { yarn gulp "electron-$(VSCODE_ARCH)" } + exec { .\scripts\test-integration.bat --build --tfs "Integration Tests" } + displayName: Run integration tests + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 inputs: ConnectedServiceName: 'ESRP CodeSign' - FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)' + FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH),$(agent.builddirectory)/vscode-reh-win32-$(VSCODE_ARCH)' Pattern: '*.dll,*.exe,*.node' signConfigType: inlineSignParams inlineOperation: | @@ -114,38 +190,18 @@ steps: - powershell: | $ErrorActionPreference = "Stop" - .\build\azure-pipelines\win32\import-esrp-auth-cert.ps1 -AuthCertificateBase64 $(ESRP_AUTH_CERTIFICATE) -AuthCertificateKey $(ESRP_AUTH_CERTIFICATE_KEY) + .\build\azure-pipelines\win32\import-esrp-auth-cert.ps1 -AuthCertificateBase64 $(esrp-auth-certificate) -AuthCertificateKey $(esrp-auth-certificate-key) displayName: Import ESRP Auth Certificate - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" - exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-archive" "vscode-win32-$(VSCODE_ARCH)-system-setup" "vscode-win32-$(VSCODE_ARCH)-user-setup" --sign } - - $Repo = "$(pwd)" - $Root = "$Repo\.." - $SystemExe = "$Repo\.build\win32-$(VSCODE_ARCH)\system-setup\VSCodeSetup.exe" - $UserExe = "$Repo\.build\win32-$(VSCODE_ARCH)\user-setup\VSCodeSetup.exe" - $Zip = "$Repo\.build\win32-$(VSCODE_ARCH)\archive\VSCode-win32-$(VSCODE_ARCH).zip" - $Build = "$Root\VSCode-win32-$(VSCODE_ARCH)" - - # get version - $PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json - $Version = $PackageJson.version - $Quality = "$env:VSCODE_QUALITY" - $env:AZURE_STORAGE_ACCESS_KEY_2 = "$(AZURE_STORAGE_ACCESS_KEY_2)" - $env:MOONCAKE_STORAGE_ACCESS_KEY = "$(MOONCAKE_STORAGE_ACCESS_KEY)" - $env:AZURE_DOCUMENTDB_MASTERKEY = "$(AZURE_DOCUMENTDB_MASTERKEY)" - - $assetPlatform = if ("$(VSCODE_ARCH)" -eq "ia32") { "win32" } else { "win32-x64" } - - exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform-archive" archive "VSCode-win32-$(VSCODE_ARCH)-$Version.zip" $Version true $Zip } - exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform" setup "VSCodeSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $SystemExe } - exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform-user" setup "VSCodeUserSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $UserExe } - - # publish hockeyapp symbols - $hockeyAppId = if ("$(VSCODE_ARCH)" -eq "ia32") { "$(VSCODE_HOCKEYAPP_ID_WIN32)" } else { "$(VSCODE_HOCKEYAPP_ID_WIN64)" } - exec { node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" $hockeyAppId } + $env:AZURE_STORAGE_ACCESS_KEY_2 = "$(vscode-storage-key)" + $env:AZURE_DOCUMENTDB_MASTERKEY = "$(builds-docdb-key-readwrite)" + $env:VSCODE_HOCKEYAPP_TOKEN = "$(vscode-hockeyapp-token)" + $env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" + .\build\azure-pipelines\win32\publish.ps1 + displayName: Publish - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: 'Component Detection' diff --git a/build/azure-pipelines/win32/publish.ps1 b/build/azure-pipelines/win32/publish.ps1 new file mode 100644 index 00000000000..86da6df4e0a --- /dev/null +++ b/build/azure-pipelines/win32/publish.ps1 @@ -0,0 +1,37 @@ +. build/azure-pipelines/win32/exec.ps1 +$ErrorActionPreference = "Stop" + +$Arch = "$env:VSCODE_ARCH" + +exec { yarn gulp "vscode-win32-$Arch-archive" "vscode-win32-$Arch-system-setup" "vscode-win32-$Arch-user-setup" --sign } + +$Repo = "$(pwd)" +$Root = "$Repo\.." +$SystemExe = "$Repo\.build\win32-$Arch\system-setup\VSCodeSetup.exe" +$UserExe = "$Repo\.build\win32-$Arch\user-setup\VSCodeSetup.exe" +$Zip = "$Repo\.build\win32-$Arch\archive\VSCode-win32-$Arch.zip" +$LegacyServer = "$Root\vscode-reh-win32-$Arch" +$ServerName = "vscode-server-win32-$Arch" +$Server = "$Root\$ServerName" +$ServerZip = "$Repo\.build\vscode-server-win32-$Arch.zip" +$Build = "$Root\VSCode-win32-$Arch" + +# Create server archive +exec { Rename-Item -Path $LegacyServer -NewName $ServerName } +exec { .\node_modules\7zip\7zip-lite\7z.exe a -tzip $ServerZip $Server -r } + +# get version +$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json +$Version = $PackageJson.version +$Quality = "$env:VSCODE_QUALITY" + +$AssetPlatform = if ("$Arch" -eq "ia32") { "win32" } else { "win32-x64" } + +exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-archive" archive "VSCode-win32-$Arch-$Version.zip" $Version true $Zip } +exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform" setup "VSCodeSetup-$Arch-$Version.exe" $Version true $SystemExe } +exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-user" setup "VSCodeUserSetup-$Arch-$Version.exe" $Version true $UserExe } +exec { node build/azure-pipelines/common/publish.js $Quality "server-$AssetPlatform" archive "vscode-server-win32-$Arch.zip" $Version true $ServerZip } + +# publish hockeyapp symbols +$hockeyAppId = if ("$Arch" -eq "ia32") { "$env:VSCODE_HOCKEYAPP_ID_WIN32" } else { "$env:VSCODE_HOCKEYAPP_ID_WIN64" } +exec { node build/azure-pipelines/common/symbols.js "$env:VSCODE_MIXIN_PASSWORD" "$env:VSCODE_HOCKEYAPP_TOKEN" "$Arch" $hockeyAppId } diff --git a/build/builtInExtensions.json b/build/builtInExtensions.json index b4b5bcdfb87..a3483f451e2 100644 --- a/build/builtInExtensions.json +++ b/build/builtInExtensions.json @@ -1,7 +1,7 @@ [ { "name": "ms-vscode.node-debug", - "version": "1.30.4", + "version": "1.35.3", "repo": "https://github.com/Microsoft/vscode-node-debug", "metadata": { "id": "b6ded8fb-a0a0-4c1c-acbd-ab2a3bc995a6", @@ -16,7 +16,7 @@ }, { "name": "ms-vscode.node-debug2", - "version": "1.31.2", + "version": "1.33.0", "repo": "https://github.com/Microsoft/vscode-node-debug2", "metadata": { "id": "36d19e17-7569-4841-a001-947eb18602b2", @@ -31,7 +31,7 @@ }, { "name": "ms-vscode.references-view", - "version": "0.0.21", + "version": "0.0.29", "repo": "https://github.com/Microsoft/vscode-reference-view", "metadata": { "id": "dc489f46-520d-4556-ae85-1f9eab3c412d", diff --git a/build/builtin/main.js b/build/builtin/main.js index 849027ad2b9..b094a67cac5 100644 --- a/build/builtin/main.js +++ b/build/builtin/main.js @@ -10,7 +10,7 @@ const path = require('path'); let window = null; app.once('ready', () => { - window = new BrowserWindow({ width: 800, height: 600 }); + window = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, webviewTag: true } }); window.setMenuBarVisibility(false); window.loadURL(url.format({ pathname: path.join(__dirname, 'index.html'), protocol: 'file:', slashes: true })); // window.webContents.openDevTools(); diff --git a/build/gulpfile.compile.js b/build/gulpfile.compile.js new file mode 100644 index 00000000000..21aa7896558 --- /dev/null +++ b/build/gulpfile.compile.js @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +const gulp = require('gulp'); +const util = require('./lib/util'); +const task = require('./lib/task'); +const compilation = require('./lib/compilation'); + +// Full compile, including nls and inline sources in sourcemaps, for build +const compileBuildTask = task.define('compile-build', task.series(util.rimraf('out-build'), compilation.compileTask('src', 'out-build', true))); +gulp.task(compileBuildTask); +exports.compileBuildTask = compileBuildTask; \ No newline at end of file diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js index e59be13ea3e..7bbf246a8dc 100644 --- a/build/gulpfile.editor.js +++ b/build/gulpfile.editor.js @@ -6,6 +6,7 @@ const gulp = require('gulp'); const path = require('path'); const util = require('./lib/util'); +const task = require('./lib/task'); const common = require('./lib/optimize'); const es = require('event-stream'); const File = require('vinyl'); @@ -48,9 +49,6 @@ var editorResources = [ '!**/test/**' ]; -var editorOtherSources = [ -]; - var BUNDLED_FILE_HEADER = [ '/*!-----------------------------------------------------------', ' * Copyright (c) Microsoft Corporation. All rights reserved.', @@ -63,8 +61,7 @@ var BUNDLED_FILE_HEADER = [ const languages = i18n.defaultLanguages.concat([]); // i18n.defaultLanguages.concat(process.env.VSCODE_QUALITY !== 'stable' ? i18n.extraLanguages : []); -gulp.task('clean-editor-src', util.rimraf('out-editor-src')); -gulp.task('extract-editor-src', ['clean-editor-src'], function () { +const extractEditorSrcTask = task.define('extract-editor-src', () => { console.log(`If the build fails, consider tweaking shakeLevel below to a lower value.`); const apiusages = monacoapi.execute().usageContent; const extrausages = fs.readFileSync(path.join(root, 'build', 'monaco', 'monaco.usage.recipe')).toString(); @@ -84,6 +81,7 @@ gulp.task('extract-editor-src', ['clean-editor-src'], function () { 'typings/thenable.d.ts', 'typings/es6-promise.d.ts', 'typings/require-monaco.d.ts', + "typings/lib.es2018.promise.d.ts", 'vs/monaco.d.ts' ], libs: [ @@ -100,15 +98,11 @@ gulp.task('extract-editor-src', ['clean-editor-src'], function () { }); }); -// Full compile, including nls and inline sources in sourcemaps, for build -gulp.task('clean-editor-build', util.rimraf('out-editor-build')); -gulp.task('compile-editor-build', ['clean-editor-build', 'extract-editor-src'], compilation.compileTask('out-editor-src', 'out-editor-build', true)); +const compileEditorAMDTask = task.define('compile-editor-amd', compilation.compileTask('out-editor-src', 'out-editor-build', true)); -gulp.task('clean-optimized-editor', util.rimraf('out-editor')); -gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-editor-build'], common.optimizeTask({ +const optimizeEditorAMDTask = task.define('optimize-editor-amd', common.optimizeTask({ src: 'out-editor-build', entryPoints: editorEntryPoints, - otherSources: editorOtherSources, resources: editorResources, loaderConfig: { paths: { @@ -125,11 +119,9 @@ gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-editor-build'], languages: languages })); -gulp.task('clean-minified-editor', util.rimraf('out-editor-min')); -gulp.task('minify-editor', ['clean-minified-editor', 'optimize-editor'], common.minifyTask('out-editor')); +const minifyEditorAMDTask = task.define('minify-editor-amd', common.minifyTask('out-editor')); -gulp.task('clean-editor-esm', util.rimraf('out-editor-esm')); -gulp.task('extract-editor-esm', ['clean-editor-esm', 'clean-editor-distro', 'extract-editor-src'], function () { +const createESMSourcesAndResourcesTask = task.define('extract-editor-esm', () => { standalone.createESMSourcesAndResources2({ srcFolder: './out-editor-src', outFolder: './out-editor-esm', @@ -151,7 +143,8 @@ gulp.task('extract-editor-esm', ['clean-editor-esm', 'clean-editor-distro', 'ext } }); }); -gulp.task('compile-editor-esm', ['extract-editor-esm', 'clean-editor-distro'], function () { + +const compileEditorESMTask = task.define('compile-editor-esm', () => { if (process.platform === 'win32') { const result = cp.spawnSync(`..\\node_modules\\.bin\\tsc.cmd`, { cwd: path.join(__dirname, '../out-editor-esm') @@ -202,8 +195,16 @@ function toExternalDTS(contents) { return lines.join('\n'); } -gulp.task('clean-editor-distro', util.rimraf('out-monaco-editor-core')); -gulp.task('editor-distro', ['clean-editor-distro', 'compile-editor-esm', 'minify-editor', 'optimize-editor'], function () { +function filterStream(testFunc) { + return es.through(function (data) { + if (!testFunc(data.relative)) { + return; + } + this.emit('data', data); + }); +} + +const finalEditorResourcesTask = task.define('final-editor-resources', () => { return es.merge( // other assets es.merge( @@ -233,6 +234,14 @@ gulp.task('editor-distro', ['clean-editor-distro', 'compile-editor-esm', 'minify })) .pipe(gulp.dest('out-monaco-editor-core')), + // version.txt + gulp.src('build/monaco/version.txt') + .pipe(es.through(function (data) { + data.contents = Buffer.from(`monaco-editor-core: https://github.com/Microsoft/vscode/tree/${sha1}`); + this.emit('data', data); + })) + .pipe(gulp.dest('out-monaco-editor-core')), + // README.md gulp.src('build/monaco/README-npm.md') .pipe(es.through(function (data) { @@ -266,7 +275,7 @@ gulp.task('editor-distro', ['clean-editor-distro', 'compile-editor-esm', 'minify var strContents = data.contents.toString(); var newStr = '//# sourceMappingURL=' + relativePathToMap.replace(/\\/g, '/'); - strContents = strContents.replace(/\/\/\# sourceMappingURL=[^ ]+$/, newStr); + strContents = strContents.replace(/\/\/# sourceMappingURL=[^ ]+$/, newStr); data.contents = Buffer.from(strContents); this.emit('data', data); @@ -282,59 +291,31 @@ gulp.task('editor-distro', ['clean-editor-distro', 'compile-editor-esm', 'minify ); }); -gulp.task('analyze-editor-distro', function () { - // @ts-ignore - var bundleInfo = require('../out-editor/bundleInfo.json'); - var graph = bundleInfo.graph; - var bundles = bundleInfo.bundles; - - var inverseGraph = {}; - Object.keys(graph).forEach(function (module) { - var dependencies = graph[module]; - dependencies.forEach(function (dep) { - inverseGraph[dep] = inverseGraph[dep] || []; - inverseGraph[dep].push(module); - }); - }); - - var detailed = {}; - Object.keys(bundles).forEach(function (entryPoint) { - var included = bundles[entryPoint]; - var includedMap = {}; - included.forEach(function (included) { - includedMap[included] = true; - }); - - var explanation = []; - included.map(function (included) { - if (included.indexOf('!') >= 0) { - return; - } - - var reason = (inverseGraph[included] || []).filter(function (mod) { - return !!includedMap[mod]; - }); - explanation.push({ - module: included, - reason: reason - }); - }); - - detailed[entryPoint] = explanation; - }); - - console.log(JSON.stringify(detailed, null, '\t')); -}); - -function filterStream(testFunc) { - return es.through(function (data) { - if (!testFunc(data.relative)) { - return; - } - this.emit('data', data); - }); -} - +gulp.task('editor-distro', + task.series( + task.parallel( + util.rimraf('out-editor-src'), + util.rimraf('out-editor-build'), + util.rimraf('out-editor-esm'), + util.rimraf('out-monaco-editor-core'), + util.rimraf('out-editor'), + util.rimraf('out-editor-min') + ), + extractEditorSrcTask, + task.parallel( + task.series( + compileEditorAMDTask, + optimizeEditorAMDTask, + minifyEditorAMDTask + ), + task.series( + createESMSourcesAndResourcesTask, + compileEditorESMTask + ) + ), + finalEditorResourcesTask + ) +); //#region monaco type checking @@ -354,6 +335,7 @@ function createTscCompileTask(watch) { let errors = []; let reporter = createReporter(); let report; + // eslint-disable-next-line no-control-regex let magic = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; // https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings child.stdout.on('data', data => { @@ -387,7 +369,10 @@ function createTscCompileTask(watch) { }; } -gulp.task('monaco-typecheck-watch', createTscCompileTask(true)); -gulp.task('monaco-typecheck', createTscCompileTask(false)); +const monacoTypecheckWatchTask = task.define('monaco-typecheck-watch', createTscCompileTask(true)); +exports.monacoTypecheckWatchTask = monacoTypecheckWatchTask; + +const monacoTypecheckTask = task.define('monaco-typecheck', createTscCompileTask(false)); +exports.monacoTypecheckTask = monacoTypecheckTask; //#endregion diff --git a/build/gulpfile.extensions.js b/build/gulpfile.extensions.js index 1488f96ec44..e4f7b58d50a 100644 --- a/build/gulpfile.extensions.js +++ b/build/gulpfile.extensions.js @@ -11,8 +11,8 @@ const path = require('path'); const tsb = require('gulp-tsb'); const es = require('event-stream'); const filter = require('gulp-filter'); -const rimraf = require('rimraf'); const util = require('./lib/util'); +const task = require('./lib/task'); const watcher = require('./lib/watch'); const createReporter = require('./lib/reporter').createReporter; const glob = require('glob'); @@ -22,6 +22,7 @@ const root = path.dirname(__dirname); const commit = util.getVersion(root); const plumber = require('gulp-plumber'); const _ = require('underscore'); +const ext = require('./lib/extensions'); const extensionsPath = path.join(path.dirname(__dirname), 'extensions'); @@ -43,16 +44,6 @@ const tasks = compilations.map(function (tsconfigFile) { const name = relativeDirname.replace(/\//g, '-'); - // Tasks - const clean = 'clean-extension:' + name; - const compile = 'compile-extension:' + name; - const watch = 'watch-extension:' + name; - - // Build Tasks - const cleanBuild = 'clean-extension-build:' + name; - const compileBuild = 'compile-extension-build:' + name; - const watchBuild = 'watch-extension-build:' + name; - const root = path.join('extensions', relativeDirname); const srcBase = path.join(root, 'src'); const src = path.join(srcBase, '**'); @@ -111,18 +102,18 @@ const tasks = compilations.map(function (tsconfigFile) { const srcOpts = { cwd: path.dirname(__dirname), base: srcBase }; - gulp.task(clean, cb => rimraf(out, cb)); + const cleanTask = task.define(`clean-extension-${name}`, util.rimraf(out)); - gulp.task(compile, [clean], () => { + const compileTask = task.define(`compile-extension:${name}`, task.series(cleanTask, () => { const pipeline = createPipeline(false, true); const input = gulp.src(src, srcOpts); return input .pipe(pipeline()) .pipe(gulp.dest(out)); - }); + })); - gulp.task(watch, [clean], () => { + const watchTask = task.define(`watch-extension:${name}`, task.series(cleanTask, () => { const pipeline = createPipeline(false); const input = gulp.src(src, srcOpts); const watchInput = watcher(src, srcOpts); @@ -130,43 +121,43 @@ const tasks = compilations.map(function (tsconfigFile) { return watchInput .pipe(util.incremental(pipeline, input)) .pipe(gulp.dest(out)); - }); + })); - gulp.task(cleanBuild, cb => rimraf(out, cb)); - - gulp.task(compileBuild, [clean], () => { + const compileBuildTask = task.define(`compile-build-extension-${name}`, task.series(cleanTask, () => { const pipeline = createPipeline(true, true); const input = gulp.src(src, srcOpts); return input .pipe(pipeline()) .pipe(gulp.dest(out)); - }); + })); - gulp.task(watchBuild, [clean], () => { - const pipeline = createPipeline(true); - const input = gulp.src(src, srcOpts); - const watchInput = watcher(src, srcOpts); + // Tasks + gulp.task(compileTask); + gulp.task(watchTask); - return watchInput - .pipe(util.incremental(() => pipeline(), input)) - .pipe(gulp.dest(out)); - }); - - return { - clean: clean, - compile: compile, - watch: watch, - cleanBuild: cleanBuild, - compileBuild: compileBuild, - watchBuild: watchBuild - }; + return { compileTask, watchTask, compileBuildTask }; }); -gulp.task('clean-extensions', tasks.map(t => t.clean)); -gulp.task('compile-extensions', tasks.map(t => t.compile)); -gulp.task('watch-extensions', tasks.map(t => t.watch)); +const compileExtensionsTask = task.define('compile-extensions', task.parallel(...tasks.map(t => t.compileTask))); +gulp.task(compileExtensionsTask); +exports.compileExtensionsTask = compileExtensionsTask; -gulp.task('clean-extensions-build', tasks.map(t => t.cleanBuild)); -gulp.task('compile-extensions-build', tasks.map(t => t.compileBuild)); -gulp.task('watch-extensions-build', tasks.map(t => t.watchBuild)); +const watchExtensionsTask = task.define('watch-extensions', task.parallel(...tasks.map(t => t.watchTask))); +gulp.task(watchExtensionsTask); +exports.watchExtensionsTask = watchExtensionsTask; + +const compileExtensionsBuildLegacyTask = task.define('compile-extensions-build-legacy', task.parallel(...tasks.map(t => t.compileBuildTask))); +gulp.task(compileExtensionsBuildLegacyTask); + +// Azure Pipelines + +const cleanExtensionsBuildTask = task.define('clean-extensions-build', util.rimraf('.build/extensions')); +const compileExtensionsBuildTask = task.define('compile-extensions-build', task.series( + cleanExtensionsBuildTask, + task.define('bundle-extensions-build', () => ext.packageLocalExtensionsStream().pipe(gulp.dest('.build'))), + task.define('bundle-marketplace-extensions-build', () => ext.packageMarketplaceExtensionsStream().pipe(gulp.dest('.build'))), +)); + +gulp.task(compileExtensionsBuildTask); +exports.compileExtensionsBuildTask = compileExtensionsBuildTask; \ No newline at end of file diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 1af30179a06..f6594804322 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -42,7 +42,8 @@ const indentationFilter = [ // except specific files '!ThirdPartyNotices.txt', - '!LICENSE.txt', + '!LICENSE.{txt,rtf}', + '!LICENSES.chromium.html', '!**/LICENSE', '!src/vs/nls.js', '!src/vs/nls.build.js', @@ -81,11 +82,12 @@ const indentationFilter = [ '!src/typings/**/*.d.ts', '!extensions/**/*.d.ts', '!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe,ico,icns}', - '!build/{lib,tslintRules}/**/*.js', + '!build/{lib,tslintRules,download}/**/*.js', '!build/**/*.sh', '!build/azure-pipelines/**/*.js', '!build/azure-pipelines/**/*.config', '!**/Dockerfile', + '!**/Dockerfile.*', '!**/*.Dockerfile', '!**/*.dockerfile', '!extensions/markdown-language-features/media/*.js' @@ -117,7 +119,8 @@ const copyrightFilter = [ '!resources/completions/**', '!extensions/markdown-language-features/media/highlight.css', '!extensions/html-language-features/server/src/modes/typescript/*', - '!extensions/*/server/bin/*' + '!extensions/*/server/bin/*', + '!src/vs/editor/test/node/classification/typescript-test.ts', ]; const eslintFilter = [ @@ -173,6 +176,17 @@ gulp.task('tslint', () => { function hygiene(some) { let errorCount = 0; + const productJson = es.through(function (file) { + const product = JSON.parse(file.contents.toString('utf8')); + + if (product.extensionsGallery) { + console.error('product.json: Contains "extensionsGallery"'); + errorCount++; + } + + this.emit('data', file); + }); + const indentation = es.through(function (file) { const lines = file.contents.toString('utf8').split(/\r\n|\r|\n/); file.__lines = lines; @@ -228,7 +242,7 @@ function hygiene(some) { let formatted = result.dest.replace(/\r\n/gm, '\n'); if (original !== formatted) { - console.error('File not formatted:', file.relative); + console.error("File not formatted. Run the 'Format Document' command to fix it:", file.relative); errorCount++; } cb(null, file); @@ -256,8 +270,13 @@ function hygiene(some) { input = some; } + const productJsonFilter = filter('product.json', { restore: true }); + const result = input .pipe(filter(f => !f.stat.isDirectory())) + .pipe(productJsonFilter) + .pipe(process.env['BUILD_SOURCEVERSION'] ? es.through() : productJson) + .pipe(productJsonFilter.restore) .pipe(filter(indentationFilter)) .pipe(indentation) .pipe(filter(copyrightFilter)) diff --git a/build/gulpfile.mixin.js b/build/gulpfile.mixin.js deleted file mode 100644 index 0b032152cf9..00000000000 --- a/build/gulpfile.mixin.js +++ /dev/null @@ -1,69 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -const gulp = require('gulp'); -const json = require('gulp-json-editor'); -const buffer = require('gulp-buffer'); -const filter = require('gulp-filter'); -const es = require('event-stream'); -const util = require('./lib/util'); -const remote = require('gulp-remote-src'); -const zip = require('gulp-vinyl-zip'); - -const pkg = require('../package.json'); - -gulp.task('mixin', function () { - const repo = process.env['VSCODE_MIXIN_REPO']; - - if (!repo) { - console.log('Missing VSCODE_MIXIN_REPO, skipping mixin'); - return; - } - - const quality = process.env['VSCODE_QUALITY']; - - if (!quality) { - console.log('Missing VSCODE_QUALITY, skipping mixin'); - return; - } - - const url = `https://github.com/${repo}/archive/${pkg.distro}.zip`; - const opts = { base: url }; - const username = process.env['VSCODE_MIXIN_USERNAME']; - const password = process.env['VSCODE_MIXIN_PASSWORD']; - - if (username || password) { - opts.auth = { user: username || '', pass: password || '' }; - } - - console.log('Mixing in sources from \'' + url + '\':'); - - let all = remote('', opts) - .pipe(zip.src()) - .pipe(filter(function (f) { return !f.isDirectory(); })) - .pipe(util.rebase(1)); - - if (quality) { - const productJsonFilter = filter('product.json', { restore: true }); - const mixin = all - .pipe(filter(['quality/' + quality + '/**'])) - .pipe(util.rebase(2)) - .pipe(productJsonFilter) - .pipe(buffer()) - .pipe(json(o => Object.assign({}, require('../product.json'), o))) - .pipe(productJsonFilter.restore); - - all = es.merge(mixin); - } - - return all - .pipe(es.mapSync(function (f) { - console.log(f.relative); - return f; - })) - .pipe(gulp.dest('.')); -}); \ No newline at end of file diff --git a/build/gulpfile.reh.js b/build/gulpfile.reh.js new file mode 100644 index 00000000000..a956fba979e --- /dev/null +++ b/build/gulpfile.reh.js @@ -0,0 +1,145 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +const gulp = require('gulp'); + +const path = require('path'); +const es = require('event-stream'); +const util = require('./lib/util'); +const task = require('./lib/task'); +const vfs = require('vinyl-fs'); +const flatmap = require('gulp-flatmap'); +const gunzip = require('gulp-gunzip'); +const untar = require('gulp-untar'); +const File = require('vinyl'); +const fs = require('fs'); +const remote = require('gulp-remote-retry-src'); +const rename = require('gulp-rename'); +const filter = require('gulp-filter'); +const cp = require('child_process'); + +const REPO_ROOT = path.dirname(__dirname); + +const BUILD_TARGETS = [ + { platform: 'win32', arch: 'ia32', pkgTarget: 'node8-win-x86' }, + { platform: 'win32', arch: 'x64', pkgTarget: 'node8-win-x64' }, + { platform: 'darwin', arch: null, pkgTarget: 'node8-macos-x64' }, + { platform: 'linux', arch: 'ia32', pkgTarget: 'node8-linux-x86' }, + { platform: 'linux', arch: 'x64', pkgTarget: 'node8-linux-x64' }, + { platform: 'linux', arch: 'armhf', pkgTarget: 'node8-linux-armv7' }, + { platform: 'linux', arch: 'arm64', pkgTarget: 'node8-linux-arm64' }, + { platform: 'linux', arch: 'alpine', pkgTarget: 'node8-linux-alpine' }, +]; + +const noop = () => { return Promise.resolve(); }; + +gulp.task('vscode-reh-win32-ia32-min', noop); +gulp.task('vscode-reh-win32-x64-min', noop); +gulp.task('vscode-reh-darwin-min', noop); +gulp.task('vscode-reh-linux-x64-min', noop); +gulp.task('vscode-reh-linux-armhf-min', noop); +gulp.task('vscode-reh-linux-arm64-min', noop); +gulp.task('vscode-reh-linux-alpine-min', noop); + +gulp.task('vscode-reh-web-win32-ia32-min', noop); +gulp.task('vscode-reh-web-win32-x64-min', noop); +gulp.task('vscode-reh-web-darwin-min', noop); +gulp.task('vscode-reh-web-linux-x64-min', noop); +gulp.task('vscode-reh-web-linux-alpine-min', noop); + +function getNodeVersion() { + const yarnrc = fs.readFileSync(path.join(REPO_ROOT, 'remote', '.yarnrc'), 'utf8'); + const target = /^target "(.*)"$/m.exec(yarnrc)[1]; + return target; +} + +const nodeVersion = getNodeVersion(); + +BUILD_TARGETS.forEach(({ platform, arch }) => { + if (platform === 'darwin') { + arch = 'x64'; + } + + gulp.task(task.define(`node-${platform}-${arch}`, () => { + const nodePath = path.join('.build', 'node', `v${nodeVersion}`, `${platform}-${arch}`); + + if (!fs.existsSync(nodePath)) { + util.rimraf(nodePath); + + return nodejs(platform, arch) + .pipe(vfs.dest(nodePath)); + } + + return Promise.resolve(null); + })); +}); + +const defaultNodeTask = gulp.task(`node-${process.platform}-${process.arch}`); + +if (defaultNodeTask) { + gulp.task(task.define('node', defaultNodeTask)); +} + +function nodejs(platform, arch) { + if (arch === 'ia32') { + arch = 'x86'; + } + + if (platform === 'win32') { + return remote(`/dist/v${nodeVersion}/win-${arch}/node.exe`, { base: 'https://nodejs.org' }) + .pipe(rename('node.exe')); + } + + if (arch === 'alpine') { + const contents = cp.execSync(`docker run --rm node:${nodeVersion}-alpine /bin/sh -c 'cat \`which node\`'`, { maxBuffer: 100 * 1024 * 1024, encoding: 'buffer' }); + return es.readArray([new File({ path: 'node', contents, stat: { mode: parseInt('755', 8) } })]); + } + + if (platform === 'darwin') { + arch = 'x64'; + } + + if (arch === 'armhf') { + arch = 'armv7l'; + } + + return remote(`/dist/v${nodeVersion}/node-v${nodeVersion}-${platform}-${arch}.tar.gz`, { base: 'https://nodejs.org' }) + .pipe(flatmap(stream => stream.pipe(gunzip()).pipe(untar()))) + .pipe(filter('**/node')) + .pipe(util.setExecutableBit('**')) + .pipe(rename('node')); +} + +function mixinServer(watch) { + const packageJSONPath = path.join(path.dirname(__dirname), 'package.json'); + function exec(cmdLine) { + console.log(cmdLine); + cp.execSync(cmdLine, { stdio: "inherit" }); + } + function checkout() { + const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString()); + exec('git fetch distro'); + exec(`git checkout ${packageJSON['distro']} -- src/vs/server resources/server`); + exec('git reset HEAD src/vs/server resources/server'); + } + checkout(); + if (watch) { + console.log('Enter watch mode (observing package.json)'); + const watcher = fs.watch(packageJSONPath); + watcher.addListener('change', () => { + try { + checkout(); + } catch (e) { + console.log(e); + } + }); + } + return Promise.resolve(); +} + +gulp.task(task.define('mixin-server', () => mixinServer(false))); +gulp.task(task.define('mixin-server-watch', () => mixinServer(true))); diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index d68e419c570..99bd930a91c 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -20,7 +20,7 @@ const filter = require('gulp-filter'); const json = require('gulp-json-editor'); const _ = require('underscore'); const util = require('./lib/util'); -const ext = require('./lib/extensions'); +const task = require('./lib/task'); const buildfile = require('../src/buildfile'); const common = require('./lib/optimize'); const root = path.dirname(__dirname); @@ -33,6 +33,8 @@ const deps = require('./dependencies'); const getElectronVersion = require('./lib/electron').getElectronVersion; const createAsar = require('./lib/asar').createAsar; const minimist = require('minimist'); +const { compileBuildTask } = require('./gulpfile.compile'); +const { compileExtensionsBuildTask } = require('./gulpfile.extensions'); const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname)); // @ts-ignore @@ -47,6 +49,7 @@ const nodeModules = ['electron', 'original-fs'] const vscodeEntryPoints = _.flatten([ buildfile.entrypoint('vs/workbench/workbench.main'), buildfile.base, + buildfile.serviceWorker, buildfile.workbench, buildfile.code ]); @@ -60,19 +63,22 @@ const vscodeResources = [ 'out-build/bootstrap-amd.js', 'out-build/bootstrap-window.js', 'out-build/paths.js', - 'out-build/vs/**/*.{svg,png,cur,html}', + 'out-build/vs/**/*.{svg,png,html}', + '!out-build/vs/code/browser/**/*.html', 'out-build/vs/base/common/performance.js', - 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh}', + 'out-build/vs/base/node/languagePacks.js', + 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}', 'out-build/vs/base/browser/ui/octiconLabel/octicons/**', 'out-build/vs/workbench/browser/media/*-theme.css', - 'out-build/vs/workbench/parts/debug/**/*.json', - 'out-build/vs/workbench/parts/execution/**/*.scpt', - 'out-build/vs/workbench/parts/webview/electron-browser/webview-pre.js', + 'out-build/vs/workbench/contrib/debug/**/*.json', + 'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt', + 'out-build/vs/workbench/contrib/webview/browser/pre/*.js', + 'out-build/vs/workbench/contrib/webview/electron-browser/pre/*.js', 'out-build/vs/**/markdown.css', - 'out-build/vs/workbench/parts/tasks/**/*.json', - 'out-build/vs/workbench/parts/welcome/walkThrough/**/*.md', - 'out-build/vs/workbench/services/files/**/*.exe', - 'out-build/vs/workbench/services/files/**/*.md', + 'out-build/vs/workbench/contrib/tasks/**/*.json', + 'out-build/vs/workbench/contrib/welcome/walkThrough/**/*.md', + 'out-build/vs/platform/files/**/*.exe', + 'out-build/vs/platform/files/**/*.md', 'out-build/vs/code/electron-browser/workbench/**', 'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js', 'out-build/vs/code/electron-browser/issue/issueReporter.js', @@ -80,35 +86,32 @@ const vscodeResources = [ '!**/test/**' ]; -const BUNDLED_FILE_HEADER = [ - '/*!--------------------------------------------------------', - ' * Copyright (C) Microsoft Corporation. All rights reserved.', - ' *--------------------------------------------------------*/' -].join('\n'); - -gulp.task('clean-optimized-vscode', util.rimraf('out-vscode')); -gulp.task('optimize-vscode', ['clean-optimized-vscode', 'compile-build', 'compile-extensions-build'], common.optimizeTask({ - src: 'out-build', - entryPoints: vscodeEntryPoints, - otherSources: [], - resources: vscodeResources, - loaderConfig: common.loaderConfig(nodeModules), - header: BUNDLED_FILE_HEADER, - out: 'out-vscode', - bundleInfo: undefined -})); - - -gulp.task('optimize-index-js', ['optimize-vscode'], () => { - const fullpath = path.join(process.cwd(), 'out-vscode/bootstrap-window.js'); - const contents = fs.readFileSync(fullpath).toString(); - const newContents = contents.replace('[/*BUILD->INSERT_NODE_MODULES*/]', JSON.stringify(nodeModules)); - fs.writeFileSync(fullpath, newContents); -}); +const optimizeVSCodeTask = task.define('optimize-vscode', task.series( + util.rimraf('out-vscode'), + common.optimizeTask({ + src: 'out-build', + entryPoints: vscodeEntryPoints, + resources: vscodeResources, + loaderConfig: common.loaderConfig(nodeModules), + out: 'out-vscode', + bundleInfo: undefined + }) +)); +gulp.task(optimizeVSCodeTask); const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`; -gulp.task('clean-minified-vscode', util.rimraf('out-vscode-min')); -gulp.task('minify-vscode', ['clean-minified-vscode', 'optimize-index-js'], common.minifyTask('out-vscode', `${sourceMappingURLBase}/core`)); +const minifyVSCodeTask = task.define('minify-vscode', task.series( + optimizeVSCodeTask, + util.rimraf('out-vscode-min'), + () => { + const fullpath = path.join(process.cwd(), 'out-vscode/bootstrap-window.js'); + const contents = fs.readFileSync(fullpath).toString(); + const newContents = contents.replace('[/*BUILD->INSERT_NODE_MODULES*/]', JSON.stringify(nodeModules)); + fs.writeFileSync(fullpath, newContents); + }, + common.minifyTask('out-vscode', `${sourceMappingURLBase}/core`) +)); +gulp.task(minifyVSCodeTask); // Package @@ -197,13 +200,11 @@ function getElectron(arch) { }; } -gulp.task('clean-electron', util.rimraf('.build/electron')); -gulp.task('electron', ['clean-electron'], getElectron(process.arch)); -gulp.task('electron-ia32', ['clean-electron'], getElectron('ia32')); -gulp.task('electron-x64', ['clean-electron'], getElectron('x64')); -gulp.task('electron-arm', ['clean-electron'], getElectron('arm')); -gulp.task('electron-arm64', ['clean-electron'], getElectron('arm64')); - +gulp.task(task.define('electron', task.series(util.rimraf('.build/electron'), getElectron(process.arch)))); +gulp.task(task.define('electron-ia32', task.series(util.rimraf('.build/electron'), getElectron('ia32')))); +gulp.task(task.define('electron-x64', task.series(util.rimraf('.build/electron'), getElectron('x64')))); +gulp.task(task.define('electron-arm', task.series(util.rimraf('.build/electron'), getElectron('armv7l')))); +gulp.task(task.define('electron-arm64', task.series(util.rimraf('.build/electron'), getElectron('arm64')))); /** * Compute checksums for some files. @@ -239,14 +240,14 @@ function computeChecksum(filename) { return hash; } -function packageTask(platform, arch, opts) { +function packageTask(platform, arch, sourceFolderName, destinationFolderName, opts) { opts = opts || {}; - const destination = path.join(path.dirname(root), 'VSCode') + (platform ? '-' + platform : '') + (arch ? '-' + arch : ''); + const destination = path.join(path.dirname(root), destinationFolderName); platform = platform || process.platform; return () => { - const out = opts.minified ? 'out-vscode-min' : 'out-vscode'; + const out = sourceFolderName; const checksums = computeChecksums(out, [ 'vs/workbench/workbench.main.js', @@ -257,17 +258,14 @@ function packageTask(platform, arch, opts) { const src = gulp.src(out + '/**', { base: '.' }) .pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + out), 'out'); })) - .pipe(util.setExecutableBit(['**/*.sh'])) - .pipe(filter(['**', '!**/*.js.map'])); + .pipe(util.setExecutableBit(['**/*.sh'])); - const root = path.resolve(path.join(__dirname, '..')); + const extensions = gulp.src('.build/extensions/**', { base: '.build', dot: true }); - const sources = es.merge(src, ext.packageExtensionsStream({ - sourceMappingURLBase: sourceMappingURLBase - })); + const sources = es.merge(src, extensions) + .pipe(filter(['**', '!**/*.js.map'], { dot: true })); let version = packageJson.version; - // @ts-ignore JSON checking: quality is optional const quality = product.quality; if (quality && quality !== 'stable') { @@ -295,45 +293,27 @@ function packageTask(platform, arch, opts) { const productJsonStream = gulp.src(['product.json'], { base: '.' }) .pipe(json(productJsonUpdate)); - const license = gulp.src(['LICENSES.chromium.html', 'LICENSE.txt', 'ThirdPartyNotices.txt', 'licenses/**'], { base: '.' }); - - const watermark = gulp.src(['resources/letterpress.svg', 'resources/letterpress-dark.svg', 'resources/letterpress-hc.svg'], { base: '.' }); + const license = gulp.src(['LICENSES.chromium.html', product.licenseFileName, 'ThirdPartyNotices.txt', 'licenses/**'], { base: '.', allowEmpty: true }); // TODO the API should be copied to `out` during compile, not here const api = gulp.src('src/vs/vscode.d.ts').pipe(rename('out/vs/vscode.d.ts')); - const depsSrc = [ - ..._.flatten(productionDependencies.map(d => path.relative(root, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`])), - // @ts-ignore JSON checking: dependencies is optional - ..._.flatten(Object.keys(product.dependencies || {}).map(d => [`node_modules/${d}/**`, `!node_modules/${d}/**/{test,tests}/**`])) - ]; + const telemetry = gulp.src('.build/telemetry/**', { base: '.build/telemetry', dot: true }); - const deps = gulp.src(depsSrc, { base: '.', dot: true }) + const root = path.resolve(path.join(__dirname, '..')); + const dependenciesSrc = _.flatten(productionDependencies.map(d => path.relative(root, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`])); + + const deps = gulp.src(dependenciesSrc, { base: '.', dot: true }) .pipe(filter(['**', '!**/package-lock.json'])) - .pipe(util.cleanNodeModule('fsevents', ['binding.gyp', 'fsevents.cc', 'build/**', 'src/**', 'test/**'], ['**/*.node'])) - .pipe(util.cleanNodeModule('vscode-sqlite3', ['binding.gyp', 'benchmark/**', 'cloudformation/**', 'deps/**', 'test/**', 'build/**', 'src/**'], ['build/Release/*.node'])) - .pipe(util.cleanNodeModule('oniguruma', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node', 'src/*.js'])) - .pipe(util.cleanNodeModule('windows-mutex', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node'])) - .pipe(util.cleanNodeModule('native-keymap', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node'])) - .pipe(util.cleanNodeModule('native-is-elevated', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node'])) - .pipe(util.cleanNodeModule('native-watchdog', ['binding.gyp', 'build/**', 'src/**'], ['build/Release/*.node'])) - .pipe(util.cleanNodeModule('spdlog', ['binding.gyp', 'build/**', 'deps/**', 'src/**', 'test/**'], ['build/Release/*.node'])) - .pipe(util.cleanNodeModule('jschardet', ['dist/**'])) - .pipe(util.cleanNodeModule('windows-foreground-love', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node'])) - .pipe(util.cleanNodeModule('windows-process-tree', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node'])) - .pipe(util.cleanNodeModule('gc-signals', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node', 'src/index.js'])) - .pipe(util.cleanNodeModule('keytar', ['binding.gyp', 'build/**', 'src/**', 'script/**', 'node_modules/**'], ['**/*.node'])) - .pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/*.exe', 'build/Release/*.dll', 'build/Release/*.node'])) - .pipe(util.cleanNodeModule('vscode-nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['build/Release/*.node', '**/*.a'])) - .pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node'])) + .pipe(util.cleanNodeModules(path.join(__dirname, '.nativeignore'))) .pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*', '**/node-pty/build/Release/*'], 'app/node_modules.asar')); let all = es.merge( packageJsonStream, productJsonStream, license, - watermark, api, + telemetry, sources, deps ); @@ -383,12 +363,12 @@ function packageTask(platform, arch, opts) { .pipe(util.skipDirectories()) .pipe(util.fixWin32DirectoryPermissions()) .pipe(electron(_.extend({}, config, { platform, arch, ffmpegChromium: true }))) - .pipe(filter(['**', '!LICENSE', '!LICENSES.chromium.html', '!version'])); + .pipe(filter(['**', '!LICENSE', '!LICENSES.chromium.html', '!version'], { dot: true })); - result = es.merge(result, gulp.src('resources/completions/**', { base: '.' })); + // result = es.merge(result, gulp.src('resources/completions/**', { base: '.' })); if (platform === 'win32') { - result = es.merge(result, gulp.src('resources/win32/bin/code.js', { base: 'resources/win32' })); + result = es.merge(result, gulp.src('resources/win32/bin/code.js', { base: 'resources/win32', allowEmpty: true })); result = es.merge(result, gulp.src('resources/win32/bin/code.cmd', { base: 'resources/win32' }) .pipe(replace('@@NAME@@', product.nameShort)) @@ -396,14 +376,19 @@ function packageTask(platform, arch, opts) { result = es.merge(result, gulp.src('resources/win32/bin/code.sh', { base: 'resources/win32' }) .pipe(replace('@@NAME@@', product.nameShort)) + .pipe(replace('@@PRODNAME@@', product.nameLong)) + .pipe(replace('@@VERSION@@', version)) .pipe(replace('@@COMMIT@@', commit)) .pipe(replace('@@APPNAME@@', product.applicationName)) + .pipe(replace('@@DATAFOLDER@@', product.dataFolderName)) + .pipe(replace('@@QUALITY@@', quality)) .pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; }))); result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' }) .pipe(rename(product.nameShort + '.VisualElementsManifest.xml'))); } else if (platform === 'linux') { result = es.merge(result, gulp.src('resources/linux/bin/code.sh', { base: '.' }) + .pipe(replace('@@PRODNAME@@', product.nameLong)) .pipe(replace('@@NAME@@', product.applicationName)) .pipe(rename('bin/' + product.applicationName))); } @@ -423,29 +408,40 @@ function packageTask(platform, arch, opts) { const buildRoot = path.dirname(root); -gulp.task('clean-vscode-win32-ia32', util.rimraf(path.join(buildRoot, 'VSCode-win32-ia32'))); -gulp.task('clean-vscode-win32-x64', util.rimraf(path.join(buildRoot, 'VSCode-win32-x64'))); -gulp.task('clean-vscode-darwin', util.rimraf(path.join(buildRoot, 'VSCode-darwin'))); -gulp.task('clean-vscode-linux-ia32', util.rimraf(path.join(buildRoot, 'VSCode-linux-ia32'))); -gulp.task('clean-vscode-linux-x64', util.rimraf(path.join(buildRoot, 'VSCode-linux-x64'))); -gulp.task('clean-vscode-linux-arm', util.rimraf(path.join(buildRoot, 'VSCode-linux-arm'))); -gulp.task('clean-vscode-linux-arm64', util.rimraf(path.join(buildRoot, 'VSCode-linux-arm64'))); +const BUILD_TARGETS = [ + { platform: 'win32', arch: 'ia32' }, + { platform: 'win32', arch: 'x64' }, + { platform: 'darwin', arch: null, opts: { stats: true } }, + { platform: 'linux', arch: 'ia32' }, + { platform: 'linux', arch: 'x64' }, + { platform: 'linux', arch: 'arm' }, + { platform: 'linux', arch: 'arm64' }, +]; +BUILD_TARGETS.forEach(buildTarget => { + const dashed = (str) => (str ? `-${str}` : ``); + const platform = buildTarget.platform; + const arch = buildTarget.arch; + const opts = buildTarget.opts; -gulp.task('vscode-win32-ia32', ['optimize-vscode', 'clean-vscode-win32-ia32'], packageTask('win32', 'ia32')); -gulp.task('vscode-win32-x64', ['optimize-vscode', 'clean-vscode-win32-x64'], packageTask('win32', 'x64')); -gulp.task('vscode-darwin', ['optimize-vscode', 'clean-vscode-darwin'], packageTask('darwin', null, { stats: true })); -gulp.task('vscode-linux-ia32', ['optimize-vscode', 'clean-vscode-linux-ia32'], packageTask('linux', 'ia32')); -gulp.task('vscode-linux-x64', ['optimize-vscode', 'clean-vscode-linux-x64'], packageTask('linux', 'x64')); -gulp.task('vscode-linux-arm', ['optimize-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm')); -gulp.task('vscode-linux-arm64', ['optimize-vscode', 'clean-vscode-linux-arm64'], packageTask('linux', 'arm64')); + ['', 'min'].forEach(minified => { + const sourceFolderName = `out-vscode${dashed(minified)}`; + const destinationFolderName = `VSCode${dashed(platform)}${dashed(arch)}`; -gulp.task('vscode-win32-ia32-min', ['minify-vscode', 'clean-vscode-win32-ia32'], packageTask('win32', 'ia32', { minified: true })); -gulp.task('vscode-win32-x64-min', ['minify-vscode', 'clean-vscode-win32-x64'], packageTask('win32', 'x64', { minified: true })); -gulp.task('vscode-darwin-min', ['minify-vscode', 'clean-vscode-darwin'], packageTask('darwin', null, { minified: true, stats: true })); -gulp.task('vscode-linux-ia32-min', ['minify-vscode', 'clean-vscode-linux-ia32'], packageTask('linux', 'ia32', { minified: true })); -gulp.task('vscode-linux-x64-min', ['minify-vscode', 'clean-vscode-linux-x64'], packageTask('linux', 'x64', { minified: true })); -gulp.task('vscode-linux-arm-min', ['minify-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm', { minified: true })); -gulp.task('vscode-linux-arm64-min', ['minify-vscode', 'clean-vscode-linux-arm64'], packageTask('linux', 'arm64', { minified: true })); + const vscodeTaskCI = task.define(`vscode${dashed(platform)}${dashed(arch)}${dashed(minified)}-ci`, task.series( + util.rimraf(path.join(buildRoot, destinationFolderName)), + packageTask(platform, arch, sourceFolderName, destinationFolderName, opts) + )); + gulp.task(vscodeTaskCI); + + const vscodeTask = task.define(`vscode${dashed(platform)}${dashed(arch)}${dashed(minified)}`, task.series( + compileBuildTask, + compileExtensionsBuildTask, + minified ? minifyVSCodeTask : optimizeVSCodeTask, + vscodeTaskCI + )); + gulp.task(vscodeTask); + }); +}); // Transifex Localizations @@ -468,30 +464,46 @@ const apiHostname = process.env.TRANSIFEX_API_URL; const apiName = process.env.TRANSIFEX_API_NAME; const apiToken = process.env.TRANSIFEX_API_TOKEN; -gulp.task('vscode-translations-push', ['optimize-vscode'], function () { - const pathToMetadata = './out-vscode/nls.metadata.json'; - const pathToExtensions = './extensions/*'; - const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}'; +gulp.task(task.define( + 'vscode-translations-push', + task.series( + compileBuildTask, + compileExtensionsBuildTask, + optimizeVSCodeTask, + function () { + const pathToMetadata = './out-vscode/nls.metadata.json'; + const pathToExtensions = './extensions/*'; + const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}'; - return es.merge( - gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()), - gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()), - gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions()) - ).pipe(i18n.findObsoleteResources(apiHostname, apiName, apiToken) - ).pipe(i18n.pushXlfFiles(apiHostname, apiName, apiToken)); -}); + return es.merge( + gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()), + gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()), + gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions()) + ).pipe(i18n.findObsoleteResources(apiHostname, apiName, apiToken) + ).pipe(i18n.pushXlfFiles(apiHostname, apiName, apiToken)); + } + ) +)); -gulp.task('vscode-translations-export', ['optimize-vscode'], function () { - const pathToMetadata = './out-vscode/nls.metadata.json'; - const pathToExtensions = './extensions/*'; - const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}'; +gulp.task(task.define( + 'vscode-translations-export', + task.series( + compileBuildTask, + compileExtensionsBuildTask, + optimizeVSCodeTask, + function () { + const pathToMetadata = './out-vscode/nls.metadata.json'; + const pathToExtensions = './extensions/*'; + const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}'; - return es.merge( - gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()), - gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()), - gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions()) - ).pipe(vfs.dest('../vscode-translations-export')); -}); + return es.merge( + gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()), + gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()), + gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions()) + ).pipe(vfs.dest('../vscode-translations-export')); + } + ) +)); gulp.task('vscode-translations-pull', function () { return es.merge([...i18n.defaultLanguages, ...i18n.extraLanguages].map(language => { @@ -515,83 +527,8 @@ gulp.task('vscode-translations-import', function () { })); }); -// Sourcemaps - -gulp.task('upload-vscode-sourcemaps', ['vscode-darwin-min', 'minify-vscode'], () => { - const vs = gulp.src('out-vscode-min/**/*.map', { base: 'out-vscode-min' }) - .pipe(es.mapSync(f => { - f.path = `${f.base}/core/${f.relative}`; - return f; - })); - - const extensionsOut = gulp.src('extensions/**/out/**/*.map', { base: '.' }); - const extensionsDist = gulp.src('extensions/**/dist/**/*.map', { base: '.' }); - - return es.merge(vs, extensionsOut, extensionsDist) - .pipe(es.through(function (data) { - // debug - console.log('Uploading Sourcemap', data.relative); - this.emit('data', data); - })) - .pipe(azure.upload({ - account: process.env.AZURE_STORAGE_ACCOUNT, - key: process.env.AZURE_STORAGE_ACCESS_KEY, - container: 'sourcemaps', - prefix: commit + '/' - })); -}); - -const allConfigDetailsPath = path.join(os.tmpdir(), 'configuration.json'); -gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () => { - if (!shouldSetupSettingsSearch()) { - const branch = process.env.BUILD_SOURCEBRANCH; - console.log(`Only runs on master and release branches, not ${branch}`); - return; - } - - if (!fs.existsSync(allConfigDetailsPath)) { - throw new Error(`configuration file at ${allConfigDetailsPath} does not exist`); - } - - const settingsSearchBuildId = getSettingsSearchBuildId(packageJson); - if (!settingsSearchBuildId) { - throw new Error('Failed to compute build number'); - } - - return gulp.src(allConfigDetailsPath) - .pipe(azure.upload({ - account: process.env.AZURE_STORAGE_ACCOUNT, - key: process.env.AZURE_STORAGE_ACCESS_KEY, - container: 'configuration', - prefix: `${settingsSearchBuildId}/${commit}/` - })); -}); - -function shouldSetupSettingsSearch() { - const branch = process.env.BUILD_SOURCEBRANCH; - return branch && (/\/master$/.test(branch) || branch.indexOf('/release/') >= 0); -} - -function getSettingsSearchBuildId(packageJson) { - try { - const branch = process.env.BUILD_SOURCEBRANCH; - const branchId = branch.indexOf('/release/') >= 0 ? 0 : - /\/master$/.test(branch) ? 1 : - 2; // Some unexpected branch - - const out = cp.execSync(`git rev-list HEAD --count`); - const count = parseInt(out.toString()); - - // - // 1.25.1, 1,234,567 commits, master = 1250112345671 - return util.versionStringToNumber(packageJson.version) * 1e8 + count * 10 + branchId; - } catch (e) { - throw new Error('Could not determine build number: ' + e.toString()); - } -} - // This task is only run for the MacOS build -gulp.task('generate-vscode-configuration', () => { +const generateVSCodeConfigurationTask = task.define('generate-vscode-configuration', () => { return new Promise((resolve, reject) => { const buildDir = process.env['AGENT_BUILDDIRECTORY']; if (!buildDir) { @@ -627,3 +564,59 @@ gulp.task('generate-vscode-configuration', () => { }); }); }); + +const allConfigDetailsPath = path.join(os.tmpdir(), 'configuration.json'); +gulp.task(task.define( + 'upload-vscode-configuration', + task.series( + generateVSCodeConfigurationTask, + () => { + if (!shouldSetupSettingsSearch()) { + const branch = process.env.BUILD_SOURCEBRANCH; + console.log(`Only runs on master and release branches, not ${branch}`); + return; + } + + if (!fs.existsSync(allConfigDetailsPath)) { + throw new Error(`configuration file at ${allConfigDetailsPath} does not exist`); + } + + const settingsSearchBuildId = getSettingsSearchBuildId(packageJson); + if (!settingsSearchBuildId) { + throw new Error('Failed to compute build number'); + } + + return gulp.src(allConfigDetailsPath) + .pipe(azure.upload({ + account: process.env.AZURE_STORAGE_ACCOUNT, + key: process.env.AZURE_STORAGE_ACCESS_KEY, + container: 'configuration', + prefix: `${settingsSearchBuildId}/${commit}/` + })); + } + ) +)); + +function shouldSetupSettingsSearch() { + const branch = process.env.BUILD_SOURCEBRANCH; + return branch && (/\/master$/.test(branch) || branch.indexOf('/release/') >= 0); +} + +function getSettingsSearchBuildId(packageJson) { + try { + const branch = process.env.BUILD_SOURCEBRANCH; + const branchId = branch.indexOf('/release/') >= 0 ? 0 : + /\/master$/.test(branch) ? 1 : + 2; // Some unexpected branch + + const out = cp.execSync(`git rev-list HEAD --count`); + const count = parseInt(out.toString()); + + // + // 1.25.1, 1,234,567 commits, master = 1250112345671 + return util.versionStringToNumber(packageJson.version) * 1e8 + count * 10 + branchId; + } catch (e) { + throw new Error('Could not determine build number: ' + e.toString()); + } +} + diff --git a/build/gulpfile.vscode.linux.js b/build/gulpfile.vscode.linux.js index fae082779d7..a718cfb0082 100644 --- a/build/gulpfile.vscode.linux.js +++ b/build/gulpfile.vscode.linux.js @@ -12,6 +12,7 @@ const shell = require('gulp-shell'); const es = require('event-stream'); const vfs = require('vinyl-fs'); const util = require('./lib/util'); +const task = require('./lib/task'); const packageJson = require('../package.json'); const product = require('../product.json'); const rpmDependencies = require('../resources/linux/rpm/dependencies.json'); @@ -22,7 +23,7 @@ const commit = util.getVersion(root); const linuxPackageRevision = Math.floor(new Date().getTime() / 1000); function getDebPackageArch(arch) { - return { x64: 'amd64', ia32: 'i386', arm: 'armhf', arm64: "arm64" }[arch]; + return { x64: 'amd64', arm: 'armhf', arm64: "arm64" }[arch]; } function prepareDebPackage(arch) { @@ -41,7 +42,7 @@ function prepareDebPackage(arch) { .pipe(replace('@@NAME_LONG@@', product.nameLong)) .pipe(replace('@@NAME_SHORT@@', product.nameShort)) .pipe(replace('@@NAME@@', product.applicationName)) - .pipe(replace('@@ICON@@', product.applicationName)) + .pipe(replace('@@ICON@@', product.linuxIconName)) .pipe(replace('@@URLPROTOCOL@@', product.urlProtocol)); const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' }) @@ -51,13 +52,13 @@ function prepareDebPackage(arch) { .pipe(rename('usr/share/appdata/' + product.applicationName + '.appdata.xml')); const icon = gulp.src('resources/linux/code.png', { base: '.' }) - .pipe(rename('usr/share/pixmaps/' + product.applicationName + '.png')); + .pipe(rename('usr/share/pixmaps/' + product.linuxIconName + '.png')); - const bash_completion = gulp.src('resources/completions/bash/code') - .pipe(rename('usr/share/bash-completion/completions/code')); + // const bash_completion = gulp.src('resources/completions/bash/code') + // .pipe(rename('usr/share/bash-completion/completions/code')); - const zsh_completion = gulp.src('resources/completions/zsh/_code') - .pipe(rename('usr/share/zsh/vendor-completions/_code')); + // const zsh_completion = gulp.src('resources/completions/zsh/_code') + // .pipe(rename('usr/share/zsh/vendor-completions/_code')); const code = gulp.src(binaryDir + '/**/*', { base: binaryDir }) .pipe(rename(function (p) { p.dirname = 'usr/share/' + product.applicationName + '/' + p.dirname; })); @@ -93,7 +94,7 @@ function prepareDebPackage(arch) { .pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@')) .pipe(rename('DEBIAN/postinst')); - const all = es.merge(control, postinst, postrm, prerm, desktops, appdata, icon, bash_completion, zsh_completion, code); + const all = es.merge(control, postinst, postrm, prerm, desktops, appdata, icon, /* bash_completion, zsh_completion, */ code); return all.pipe(vfs.dest(destination)); }; @@ -113,7 +114,7 @@ function getRpmBuildPath(rpmArch) { } function getRpmPackageArch(arch) { - return { x64: 'x86_64', ia32: 'i386', arm: 'armhf', arm64: "arm64" }[arch]; + return { x64: 'x86_64', arm: 'armhf', arm64: "arm64" }[arch]; } function prepareRpmPackage(arch) { @@ -131,7 +132,7 @@ function prepareRpmPackage(arch) { .pipe(replace('@@NAME_LONG@@', product.nameLong)) .pipe(replace('@@NAME_SHORT@@', product.nameShort)) .pipe(replace('@@NAME@@', product.applicationName)) - .pipe(replace('@@ICON@@', product.applicationName)) + .pipe(replace('@@ICON@@', product.linuxIconName)) .pipe(replace('@@URLPROTOCOL@@', product.urlProtocol)); const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' }) @@ -141,13 +142,13 @@ function prepareRpmPackage(arch) { .pipe(rename('usr/share/appdata/' + product.applicationName + '.appdata.xml')); const icon = gulp.src('resources/linux/code.png', { base: '.' }) - .pipe(rename('BUILD/usr/share/pixmaps/' + product.applicationName + '.png')); + .pipe(rename('BUILD/usr/share/pixmaps/' + product.linuxIconName + '.png')); - const bash_completion = gulp.src('resources/completions/bash/code') - .pipe(rename('BUILD/usr/share/bash-completion/completions/code')); + // const bash_completion = gulp.src('resources/completions/bash/code') + // .pipe(rename('BUILD/usr/share/bash-completion/completions/code')); - const zsh_completion = gulp.src('resources/completions/zsh/_code') - .pipe(rename('BUILD/usr/share/zsh/site-functions/_code')); + // const zsh_completion = gulp.src('resources/completions/zsh/_code') + // .pipe(rename('BUILD/usr/share/zsh/site-functions/_code')); const code = gulp.src(binaryDir + '/**/*', { base: binaryDir }) .pipe(rename(function (p) { p.dirname = 'BUILD/usr/share/' + product.applicationName + '/' + p.dirname; })); @@ -155,6 +156,7 @@ function prepareRpmPackage(arch) { const spec = gulp.src('resources/linux/rpm/code.spec.template', { base: '.' }) .pipe(replace('@@NAME@@', product.applicationName)) .pipe(replace('@@NAME_LONG@@', product.nameLong)) + .pipe(replace('@@ICON@@', product.linuxIconName)) .pipe(replace('@@VERSION@@', packageJson.version)) .pipe(replace('@@RELEASE@@', linuxPackageRevision)) .pipe(replace('@@ARCHITECTURE@@', rpmArch)) @@ -169,7 +171,7 @@ function prepareRpmPackage(arch) { const specIcon = gulp.src('resources/linux/rpm/code.xpm', { base: '.' }) .pipe(rename('SOURCES/' + product.applicationName + '.xpm')); - const all = es.merge(code, desktops, appdata, icon, bash_completion, zsh_completion, spec, specIcon); + const all = es.merge(code, desktops, appdata, icon, /* bash_completion, zsh_completion, */ spec, specIcon); return all.pipe(vfs.dest(getRpmBuildPath(rpmArch))); }; @@ -198,14 +200,20 @@ function prepareSnapPackage(arch) { return function () { const desktop = gulp.src('resources/linux/code.desktop', { base: '.' }) + .pipe(rename(`usr/share/applications/${product.applicationName}.desktop`)); + + const desktopUrlHandler = gulp.src('resources/linux/code-url-handler.desktop', { base: '.' }) + .pipe(rename(`usr/share/applications/${product.applicationName}-url-handler.desktop`)); + + const desktops = es.merge(desktop, desktopUrlHandler) .pipe(replace('@@NAME_LONG@@', product.nameLong)) .pipe(replace('@@NAME_SHORT@@', product.nameShort)) .pipe(replace('@@NAME@@', product.applicationName)) - .pipe(replace('@@ICON@@', `/usr/share/pixmaps/${product.applicationName}.png`)) - .pipe(rename(`usr/share/applications/${product.applicationName}.desktop`)); + .pipe(replace('@@ICON@@', `/usr/share/pixmaps/${product.linuxIconName}.png`)) + .pipe(replace('@@URLPROTOCOL@@', product.urlProtocol)); const icon = gulp.src('resources/linux/code.png', { base: '.' }) - .pipe(rename(`usr/share/pixmaps/${product.applicationName}.png`)); + .pipe(rename(`usr/share/pixmaps/${product.linuxIconName}.png`)); const code = gulp.src(binaryDir + '/**/*', { base: binaryDir }) .pipe(rename(function (p) { p.dirname = `usr/share/${product.applicationName}/${p.dirname}`; })); @@ -215,13 +223,10 @@ function prepareSnapPackage(arch) { .pipe(replace('@@VERSION@@', commit.substr(0, 8))) .pipe(rename('snap/snapcraft.yaml')); - const snapUpdate = gulp.src('resources/linux/snap/snapUpdate.sh', { base: '.' }) - .pipe(rename(`usr/share/${product.applicationName}/snapUpdate.sh`)); - const electronLaunch = gulp.src('resources/linux/snap/electron-launch', { base: '.' }) .pipe(rename('electron-launch')); - const all = es.merge(desktop, icon, code, snapcraft, electronLaunch, snapUpdate); + const all = es.merge(desktops, icon, code, snapcraft, electronLaunch); return all.pipe(vfs.dest(destination)); }; @@ -232,42 +237,35 @@ function buildSnapPackage(arch) { return shell.task(`cd ${snapBuildPath} && snapcraft build`); } -gulp.task('clean-vscode-linux-ia32-deb', util.rimraf('.build/linux/deb/i386')); -gulp.task('clean-vscode-linux-x64-deb', util.rimraf('.build/linux/deb/amd64')); -gulp.task('clean-vscode-linux-arm-deb', util.rimraf('.build/linux/deb/armhf')); -gulp.task('clean-vscode-linux-arm64-deb', util.rimraf('.build/linux/deb/arm64')); -gulp.task('clean-vscode-linux-ia32-rpm', util.rimraf('.build/linux/rpm/i386')); -gulp.task('clean-vscode-linux-x64-rpm', util.rimraf('.build/linux/rpm/x86_64')); -gulp.task('clean-vscode-linux-arm-rpm', util.rimraf('.build/linux/rpm/armhf')); -gulp.task('clean-vscode-linux-arm64-rpm', util.rimraf('.build/linux/rpm/arm64')); -gulp.task('clean-vscode-linux-ia32-snap', util.rimraf('.build/linux/snap/x64')); -gulp.task('clean-vscode-linux-x64-snap', util.rimraf('.build/linux/snap/x64')); -gulp.task('clean-vscode-linux-arm-snap', util.rimraf('.build/linux/snap/x64')); -gulp.task('clean-vscode-linux-arm64-snap', util.rimraf('.build/linux/snap/x64')); +const BUILD_TARGETS = [ + { arch: 'x64' }, + { arch: 'arm' }, + { arch: 'arm64' }, +]; -gulp.task('vscode-linux-ia32-prepare-deb', ['clean-vscode-linux-ia32-deb'], prepareDebPackage('ia32')); -gulp.task('vscode-linux-x64-prepare-deb', ['clean-vscode-linux-x64-deb'], prepareDebPackage('x64')); -gulp.task('vscode-linux-arm-prepare-deb', ['clean-vscode-linux-arm-deb'], prepareDebPackage('arm')); -gulp.task('vscode-linux-arm64-prepare-deb', ['clean-vscode-linux-arm64-deb'], prepareDebPackage('arm64')); -gulp.task('vscode-linux-ia32-build-deb', ['vscode-linux-ia32-prepare-deb'], buildDebPackage('ia32')); -gulp.task('vscode-linux-x64-build-deb', ['vscode-linux-x64-prepare-deb'], buildDebPackage('x64')); -gulp.task('vscode-linux-arm-build-deb', ['vscode-linux-arm-prepare-deb'], buildDebPackage('arm')); -gulp.task('vscode-linux-arm64-build-deb', ['vscode-linux-arm64-prepare-deb'], buildDebPackage('arm64')); +BUILD_TARGETS.forEach((buildTarget) => { + const arch = buildTarget.arch; -gulp.task('vscode-linux-ia32-prepare-rpm', ['clean-vscode-linux-ia32-rpm'], prepareRpmPackage('ia32')); -gulp.task('vscode-linux-x64-prepare-rpm', ['clean-vscode-linux-x64-rpm'], prepareRpmPackage('x64')); -gulp.task('vscode-linux-arm-prepare-rpm', ['clean-vscode-linux-arm-rpm'], prepareRpmPackage('arm')); -gulp.task('vscode-linux-arm64-prepare-rpm', ['clean-vscode-linux-arm64-rpm'], prepareRpmPackage('arm64')); -gulp.task('vscode-linux-ia32-build-rpm', ['vscode-linux-ia32-prepare-rpm'], buildRpmPackage('ia32')); -gulp.task('vscode-linux-x64-build-rpm', ['vscode-linux-x64-prepare-rpm'], buildRpmPackage('x64')); -gulp.task('vscode-linux-arm-build-rpm', ['vscode-linux-arm-prepare-rpm'], buildRpmPackage('arm')); -gulp.task('vscode-linux-arm64-build-rpm', ['vscode-linux-arm64-prepare-rpm'], buildRpmPackage('arm64')); + { + const debArch = getDebPackageArch(arch); + const prepareDebTask = task.define(`vscode-linux-${arch}-prepare-deb`, task.series(util.rimraf(`.build/linux/deb/${debArch}`), prepareDebPackage(arch))); + // gulp.task(prepareDebTask); + const buildDebTask = task.define(`vscode-linux-${arch}-build-deb`, task.series(prepareDebTask, buildDebPackage(arch))); + gulp.task(buildDebTask); + } -gulp.task('vscode-linux-ia32-prepare-snap', ['clean-vscode-linux-ia32-snap'], prepareSnapPackage('ia32')); -gulp.task('vscode-linux-x64-prepare-snap', ['clean-vscode-linux-x64-snap'], prepareSnapPackage('x64')); -gulp.task('vscode-linux-arm-prepare-snap', ['clean-vscode-linux-arm-snap'], prepareSnapPackage('arm')); -gulp.task('vscode-linux-arm64-prepare-snap', ['clean-vscode-linux-arm64-snap'], prepareSnapPackage('arm64')); -gulp.task('vscode-linux-ia32-build-snap', ['vscode-linux-ia32-prepare-snap'], buildSnapPackage('ia32')); -gulp.task('vscode-linux-x64-build-snap', ['vscode-linux-x64-prepare-snap'], buildSnapPackage('x64')); -gulp.task('vscode-linux-arm-build-snap', ['vscode-linux-arm-prepare-snap'], buildSnapPackage('arm')); -gulp.task('vscode-linux-arm64-build-snap', ['vscode-linux-arm64-prepare-snap'], buildSnapPackage('arm64')); + { + const rpmArch = getRpmPackageArch(arch); + const prepareRpmTask = task.define(`vscode-linux-${arch}-prepare-rpm`, task.series(util.rimraf(`.build/linux/rpm/${rpmArch}`), prepareRpmPackage(arch))); + // gulp.task(prepareRpmTask); + const buildRpmTask = task.define(`vscode-linux-${arch}-build-rpm`, task.series(prepareRpmTask, buildRpmPackage(arch))); + gulp.task(buildRpmTask); + } + + { + const prepareSnapTask = task.define(`vscode-linux-${arch}-prepare-snap`, task.series(util.rimraf(`.build/linux/snap/${arch}`), prepareSnapPackage(arch))); + gulp.task(prepareSnapTask); + const buildSnapTask = task.define(`vscode-linux-${arch}-build-snap`, task.series(prepareSnapTask, buildSnapPackage(arch))); + gulp.task(buildSnapTask); + } +}); diff --git a/build/gulpfile.vscode.web.js b/build/gulpfile.vscode.web.js new file mode 100644 index 00000000000..11da75e482d --- /dev/null +++ b/build/gulpfile.vscode.web.js @@ -0,0 +1,151 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +const gulp = require('gulp'); +const path = require('path'); +const es = require('event-stream'); +const util = require('./lib/util'); +const task = require('./lib/task'); +const common = require('./lib/optimize'); +const product = require('../product.json'); +const rename = require('gulp-rename'); +const filter = require('gulp-filter'); +const json = require('gulp-json-editor'); +const _ = require('underscore'); +const deps = require('./dependencies'); +const vfs = require('vinyl-fs'); +const packageJson = require('../package.json'); +const { compileBuildTask } = require('./gulpfile.compile'); + +const REPO_ROOT = path.dirname(__dirname); +const commit = util.getVersion(REPO_ROOT); +const BUILD_ROOT = path.dirname(REPO_ROOT); +const WEB_FOLDER = path.join(REPO_ROOT, 'remote', 'web'); + +const productionDependencies = deps.getProductionDependencies(WEB_FOLDER); + +const nodeModules = Object.keys(product.dependencies || {}) + .concat(_.uniq(productionDependencies.map(d => d.name))); + +const vscodeWebResources = [ + + // Workbench + 'out-build/vs/{base,platform,editor,workbench}/**/*.{svg,png,html}', + 'out-build/vs/base/browser/ui/octiconLabel/octicons/**', + 'out-build/vs/**/markdown.css', + + // Webview + 'out-build/vs/workbench/contrib/webview/browser/pre/*.js', + + // Excludes + '!out-build/vs/**/{node,electron-browser,electron-main}/**', + '!out-build/vs/editor/standalone/**', + '!out-build/vs/workbench/**/*-tb.png', + '!**/test/**' +]; + +const buildfile = require('../src/buildfile'); + +const vscodeWebEntryPoints = [ + buildfile.workbenchWeb, + buildfile.serviceWorker, + buildfile.keyboardMaps, + buildfile.base +]; + +const optimizeVSCodeWebTask = task.define('optimize-vscode-web', task.series( + util.rimraf('out-vscode-web'), + common.optimizeTask({ + src: 'out-build', + entryPoints: _.flatten(vscodeWebEntryPoints), + otherSources: [], + resources: vscodeWebResources, + loaderConfig: common.loaderConfig(nodeModules), + out: 'out-vscode-web', + bundleInfo: undefined + }) +)); + +const minifyVSCodeWebTask = task.define('minify-vscode-web', task.series( + optimizeVSCodeWebTask, + util.rimraf('out-vscode-web-min'), + common.minifyTask('out-vscode-web', `https://ticino.blob.core.windows.net/sourcemaps/${commit}/core`) +)); +gulp.task(minifyVSCodeWebTask); + +function packageTask(sourceFolderName, destinationFolderName) { + const destination = path.join(BUILD_ROOT, destinationFolderName); + + return () => { + const src = gulp.src(sourceFolderName + '/**', { base: '.' }) + .pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); })) + .pipe(filter(['**', '!**/*.js.map'])); + + const sources = es.merge(src); + + let version = packageJson.version; + const quality = product.quality; + + if (quality && quality !== 'stable') { + version += '-' + quality; + } + + const name = product.nameShort; + const packageJsonStream = gulp.src(['remote/web/package.json'], { base: 'remote/web' }) + .pipe(json({ name, version })); + + const date = new Date().toISOString(); + + const productJsonStream = gulp.src(['product.json'], { base: '.' }) + .pipe(json({ commit, date })); + + const license = gulp.src(['remote/LICENSE'], { base: 'remote' }); + + const dependenciesSrc = _.flatten(productionDependencies.map(d => path.relative(REPO_ROOT, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`, `!${d}/.bin/**`])); + + const deps = gulp.src(dependenciesSrc, { base: 'remote/web', dot: true }) + .pipe(filter(['**', '!**/package-lock.json'])) + .pipe(util.cleanNodeModules(path.join(__dirname, '.nativeignore'))); + + const favicon = gulp.src('resources/server/favicon.ico', { base: 'resources/server' }); + + let all = es.merge( + packageJsonStream, + productJsonStream, + license, + sources, + deps, + favicon + ); + + let result = all + .pipe(util.skipDirectories()) + .pipe(util.fixWin32DirectoryPermissions()); + + return result.pipe(vfs.dest(destination)); + }; +} + +const dashed = (str) => (str ? `-${str}` : ``); + +['', 'min'].forEach(minified => { + const sourceFolderName = `out-vscode-web${dashed(minified)}`; + const destinationFolderName = `vscode-web`; + + const vscodeWebTaskCI = task.define(`vscode-web${dashed(minified)}-ci`, task.series( + minified ? minifyVSCodeWebTask : optimizeVSCodeWebTask, + util.rimraf(path.join(BUILD_ROOT, destinationFolderName)), + packageTask(sourceFolderName, destinationFolderName) + )); + gulp.task(vscodeWebTaskCI); + + const vscodeWebTask = task.define(`vscode-web${dashed(minified)}`, task.series( + compileBuildTask, + vscodeWebTaskCI + )); + gulp.task(vscodeWebTask); +}); \ No newline at end of file diff --git a/build/gulpfile.vscode.win32.js b/build/gulpfile.vscode.win32.js index 1cfc5b4c4f7..497fc553c03 100644 --- a/build/gulpfile.vscode.win32.js +++ b/build/gulpfile.vscode.win32.js @@ -12,6 +12,7 @@ const assert = require('assert'); const cp = require('child_process'); const _7z = require('7zip')['7z']; const util = require('./lib/util'); +const task = require('./lib/task'); const pkg = require('../package.json'); const product = require('../product.json'); const vfs = require('vinyl-fs'); @@ -24,7 +25,7 @@ const zipDir = arch => path.join(repoPath, '.build', `win32-${arch}`, 'archive') const zipPath = arch => path.join(zipDir(arch), `VSCode-win32-${arch}.zip`); const setupDir = (arch, target) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`); const issPath = path.join(__dirname, 'win32', 'code.iss'); -const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup-compiler'))), 'bin', 'ISCC.exe'); +const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup'))), 'bin', 'ISCC.exe'); const signPS1 = path.join(repoPath, 'build', 'azure-pipelines', 'win32', 'sign.ps1'); function packageInnoSetup(iss, options, cb) { @@ -105,8 +106,8 @@ function buildWin32Setup(arch, target) { } function defineWin32SetupTasks(arch, target) { - gulp.task(`clean-vscode-win32-${arch}-${target}-setup`, util.rimraf(setupDir(arch, target))); - gulp.task(`vscode-win32-${arch}-${target}-setup`, [`clean-vscode-win32-${arch}-${target}-setup`], buildWin32Setup(arch, target)); + const cleanTask = util.rimraf(setupDir(arch, target)); + gulp.task(task.define(`vscode-win32-${arch}-${target}-setup`, task.series(cleanTask, buildWin32Setup(arch, target)))); } defineWin32SetupTasks('ia32', 'system'); @@ -124,11 +125,8 @@ function archiveWin32Setup(arch) { }; } -gulp.task('clean-vscode-win32-ia32-archive', util.rimraf(zipDir('ia32'))); -gulp.task('vscode-win32-ia32-archive', ['clean-vscode-win32-ia32-archive'], archiveWin32Setup('ia32')); - -gulp.task('clean-vscode-win32-x64-archive', util.rimraf(zipDir('x64'))); -gulp.task('vscode-win32-x64-archive', ['clean-vscode-win32-x64-archive'], archiveWin32Setup('x64')); +gulp.task(task.define('vscode-win32-ia32-archive', task.series(util.rimraf(zipDir('ia32')), archiveWin32Setup('ia32')))); +gulp.task(task.define('vscode-win32-x64-archive', task.series(util.rimraf(zipDir('x64')), archiveWin32Setup('x64')))); function copyInnoUpdater(arch) { return () => { @@ -137,15 +135,17 @@ function copyInnoUpdater(arch) { }; } -gulp.task('vscode-win32-ia32-copy-inno-updater', copyInnoUpdater('ia32')); -gulp.task('vscode-win32-x64-copy-inno-updater', copyInnoUpdater('x64')); - -function patchInnoUpdater(arch) { +function updateIcon(executablePath) { return cb => { const icon = path.join(repoPath, 'resources', 'win32', 'code.ico'); - rcedit(path.join(buildPath(arch), 'tools', 'inno_updater.exe'), { icon }, cb); + rcedit(executablePath, { icon }, cb); }; } -gulp.task('vscode-win32-ia32-inno-updater', ['vscode-win32-ia32-copy-inno-updater'], patchInnoUpdater('ia32')); -gulp.task('vscode-win32-x64-inno-updater', ['vscode-win32-x64-copy-inno-updater'], patchInnoUpdater('x64')); \ No newline at end of file +gulp.task(task.define('vscode-win32-ia32-inno-updater', task.series(copyInnoUpdater('ia32'), updateIcon(path.join(buildPath('ia32'), 'tools', 'inno_updater.exe'))))); +gulp.task(task.define('vscode-win32-x64-inno-updater', task.series(copyInnoUpdater('x64'), updateIcon(path.join(buildPath('x64'), 'tools', 'inno_updater.exe'))))); + +// CodeHelper.exe icon + +gulp.task(task.define('vscode-win32-ia32-code-helper', task.series(updateIcon(path.join(buildPath('ia32'), 'resources', 'app', 'out', 'vs', 'platform', 'files', 'node', 'watcher', 'win32', 'CodeHelper.exe'))))); +gulp.task(task.define('vscode-win32-x64-code-helper', task.series(updateIcon(path.join(buildPath('x64'), 'resources', 'app', 'out', 'vs', 'platform', 'files', 'node', 'watcher', 'win32', 'CodeHelper.exe'))))); diff --git a/build/lib/builtInExtensions.js b/build/lib/builtInExtensions.js index c5797c78b61..a687bbccb4c 100644 --- a/build/lib/builtInExtensions.js +++ b/build/lib/builtInExtensions.js @@ -14,7 +14,8 @@ const es = require('event-stream'); const rename = require('gulp-rename'); const vfs = require('vinyl-fs'); const ext = require('./extensions'); -const util = require('gulp-util'); +const fancyLog = require('fancy-log'); +const ansiColors = require('ansi-colors'); const root = path.dirname(path.dirname(__dirname)); const builtInExtensions = require('../builtInExtensions.json'); @@ -43,7 +44,7 @@ function isUpToDate(extension) { function syncMarketplaceExtension(extension) { if (isUpToDate(extension)) { - util.log(util.colors.blue('[marketplace]'), `${extension.name}@${extension.version}`, util.colors.green('✔︎')); + fancyLog(ansiColors.blue('[marketplace]'), `${extension.name}@${extension.version}`, ansiColors.green('✔︎')); return es.readArray([]); } @@ -52,13 +53,13 @@ function syncMarketplaceExtension(extension) { return ext.fromMarketplace(extension.name, extension.version, extension.metadata) .pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`)) .pipe(vfs.dest('.build/builtInExtensions')) - .on('end', () => util.log(util.colors.blue('[marketplace]'), extension.name, util.colors.green('✔︎'))); + .on('end', () => fancyLog(ansiColors.blue('[marketplace]'), extension.name, ansiColors.green('✔︎'))); } function syncExtension(extension, controlState) { switch (controlState) { case 'disabled': - util.log(util.colors.blue('[disabled]'), util.colors.gray(extension.name)); + fancyLog(ansiColors.blue('[disabled]'), ansiColors.gray(extension.name)); return es.readArray([]); case 'marketplace': @@ -66,15 +67,15 @@ function syncExtension(extension, controlState) { default: if (!fs.existsSync(controlState)) { - util.log(util.colors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but that path does not exist.`)); + fancyLog(ansiColors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but that path does not exist.`)); return es.readArray([]); } else if (!fs.existsSync(path.join(controlState, 'package.json'))) { - util.log(util.colors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but there is no 'package.json' file in that directory.`)); + fancyLog(ansiColors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but there is no 'package.json' file in that directory.`)); return es.readArray([]); } - util.log(util.colors.blue('[local]'), `${extension.name}: ${util.colors.cyan(controlState)}`, util.colors.green('✔︎')); + fancyLog(ansiColors.blue('[local]'), `${extension.name}: ${ansiColors.cyan(controlState)}`, ansiColors.green('✔︎')); return es.readArray([]); } } @@ -93,8 +94,8 @@ function writeControlFile(control) { } function main() { - util.log('Syncronizing built-in extensions...'); - util.log(`You can manage built-in extensions with the ${util.colors.cyan('--builtin')} flag`); + fancyLog('Syncronizing built-in extensions...'); + fancyLog(`You can manage built-in extensions with the ${ansiColors.cyan('--builtin')} flag`); const control = readControlFile(); const streams = []; diff --git a/build/lib/compilation.js b/build/lib/compilation.js index f0468121d7a..62aff873509 100644 --- a/build/lib/compilation.js +++ b/build/lib/compilation.js @@ -16,7 +16,8 @@ const monacodts = require("../monaco/api"); const nls = require("./nls"); const reporter_1 = require("./reporter"); const util = require("./util"); -const util2 = require("gulp-util"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); const watch = require('./watch'); const reporter = reporter_1.createReporter(); function getTypeScriptCompilerOptions(src) { @@ -111,7 +112,6 @@ class MonacoGenerator { this._executeSoonTimer = null; this._isWatch = isWatch; this.stream = es.through(); - this._watchers = []; this._watchedFiles = {}; let onWillReadFile = (moduleId, filePath) => { if (!this._isWatch) { @@ -121,26 +121,10 @@ class MonacoGenerator { return; } this._watchedFiles[filePath] = true; - const watcher = fs.watch(filePath); - watcher.addListener('change', () => { + fs.watchFile(filePath, () => { this._declarationResolver.invalidateCache(moduleId); this._executeSoon(); }); - watcher.addListener('error', (err) => { - console.error(`Encountered error while watching ${filePath}.`); - console.log(err); - delete this._watchedFiles[filePath]; - for (let i = 0; i < this._watchers.length; i++) { - if (this._watchers[i] === watcher) { - this._watchers.splice(i, 1); - break; - } - } - watcher.close(); - this._declarationResolver.invalidateCache(moduleId); - this._executeSoon(); - }); - this._watchers.push(watcher); }; this._fsProvider = new class extends monacodts.FSProvider { readFileSync(moduleId, filePath) { @@ -150,11 +134,9 @@ class MonacoGenerator { }; this._declarationResolver = new monacodts.DeclarationResolver(this._fsProvider); if (this._isWatch) { - const recipeWatcher = fs.watch(monacodts.RECIPE_PATH); - recipeWatcher.addListener('change', () => { + fs.watchFile(monacodts.RECIPE_PATH, () => { this._executeSoon(); }); - this._watchers.push(recipeWatcher); } } _executeSoon() { @@ -167,9 +149,6 @@ class MonacoGenerator { this.execute(); }, 20); } - dispose() { - this._watchers.forEach(watcher => watcher.close()); - } _run() { let r = monacodts.run3(this._declarationResolver); if (!r && !this._isWatch) { @@ -179,7 +158,7 @@ class MonacoGenerator { return r; } _log(message, ...rest) { - util2.log(util2.colors.cyan('[monaco.d.ts]'), message, ...rest); + fancyLog(ansiColors.cyan('[monaco.d.ts]'), message, ...rest); } execute() { const startTime = Date.now(); diff --git a/build/lib/compilation.ts b/build/lib/compilation.ts index fede9e74492..f9544af9cc5 100644 --- a/build/lib/compilation.ts +++ b/build/lib/compilation.ts @@ -17,7 +17,9 @@ import * as monacodts from '../monaco/api'; import * as nls from './nls'; import { createReporter } from './reporter'; import * as util from './util'; -import * as util2 from 'gulp-util'; +import * as fancyLog from 'fancy-log'; +import * as ansiColors from 'ansi-colors'; + const watch = require('./watch'); const reporter = createReporter(); @@ -135,7 +137,6 @@ class MonacoGenerator { private readonly _isWatch: boolean; public readonly stream: NodeJS.ReadWriteStream; - private readonly _watchers: fs.FSWatcher[]; private readonly _watchedFiles: { [filePath: string]: boolean; }; private readonly _fsProvider: monacodts.FSProvider; private readonly _declarationResolver: monacodts.DeclarationResolver; @@ -143,7 +144,6 @@ class MonacoGenerator { constructor(isWatch: boolean) { this._isWatch = isWatch; this.stream = es.through(); - this._watchers = []; this._watchedFiles = {}; let onWillReadFile = (moduleId: string, filePath: string) => { if (!this._isWatch) { @@ -154,26 +154,10 @@ class MonacoGenerator { } this._watchedFiles[filePath] = true; - const watcher = fs.watch(filePath); - watcher.addListener('change', () => { + fs.watchFile(filePath, () => { this._declarationResolver.invalidateCache(moduleId); this._executeSoon(); }); - watcher.addListener('error', (err) => { - console.error(`Encountered error while watching ${filePath}.`); - console.log(err); - delete this._watchedFiles[filePath]; - for (let i = 0; i < this._watchers.length; i++) { - if (this._watchers[i] === watcher) { - this._watchers.splice(i, 1); - break; - } - } - watcher.close(); - this._declarationResolver.invalidateCache(moduleId); - this._executeSoon(); - }); - this._watchers.push(watcher); }; this._fsProvider = new class extends monacodts.FSProvider { public readFileSync(moduleId: string, filePath: string): Buffer { @@ -184,11 +168,9 @@ class MonacoGenerator { this._declarationResolver = new monacodts.DeclarationResolver(this._fsProvider); if (this._isWatch) { - const recipeWatcher = fs.watch(monacodts.RECIPE_PATH); - recipeWatcher.addListener('change', () => { + fs.watchFile(monacodts.RECIPE_PATH, () => { this._executeSoon(); }); - this._watchers.push(recipeWatcher); } } @@ -204,10 +186,6 @@ class MonacoGenerator { }, 20); } - public dispose(): void { - this._watchers.forEach(watcher => watcher.close()); - } - private _run(): monacodts.IMonacoDeclarationResult | null { let r = monacodts.run3(this._declarationResolver); if (!r && !this._isWatch) { @@ -218,7 +196,7 @@ class MonacoGenerator { } private _log(message: any, ...rest: any[]): void { - util2.log(util2.colors.cyan('[monaco.d.ts]'), message, ...rest); + fancyLog(ansiColors.cyan('[monaco.d.ts]'), message, ...rest); } public execute(): void { diff --git a/build/lib/electron.js b/build/lib/electron.js index 6387133675b..63e867a98fe 100644 --- a/build/lib/electron.js +++ b/build/lib/electron.js @@ -24,7 +24,7 @@ module.exports.getElectronVersion = getElectronVersion; if (require.main === module) { const version = getElectronVersion(); const versionFile = path.join(root, '.build', 'electron', 'version'); - const isUpToDate = fs.existsSync(versionFile) && fs.readFileSync(versionFile, 'utf8') === `v${version}`; + const isUpToDate = fs.existsSync(versionFile) && fs.readFileSync(versionFile, 'utf8') === `${version}`; process.exit(isUpToDate ? 0 : 1); } diff --git a/build/lib/extensions.js b/build/lib/extensions.js index 994d1336e6b..73d2c7acef3 100644 --- a/build/lib/extensions.js +++ b/build/lib/extensions.js @@ -13,26 +13,30 @@ const File = require("vinyl"); const vsce = require("vsce"); const stats_1 = require("./stats"); const util2 = require("./util"); -const remote = require("gulp-remote-src"); +const remote = require("gulp-remote-retry-src"); const vzip = require('gulp-vinyl-zip'); const filter = require("gulp-filter"); const rename = require("gulp-rename"); -const util = require('gulp-util'); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); const buffer = require('gulp-buffer'); const json = require("gulp-json-editor"); const webpack = require('webpack'); const webpackGulp = require('webpack-stream'); -const root = path.resolve(path.join(__dirname, '..', '..')); -function fromLocal(extensionPath, sourceMappingURLBase) { +const util = require('./util'); +const root = path.dirname(path.dirname(__dirname)); +const commit = util.getVersion(root); +const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`; +function fromLocal(extensionPath) { const webpackFilename = path.join(extensionPath, 'extension.webpack.config.js'); if (fs.existsSync(webpackFilename)) { - return fromLocalWebpack(extensionPath, sourceMappingURLBase); + return fromLocalWebpack(extensionPath); } else { return fromLocalNormal(extensionPath); } } -function fromLocalWebpack(extensionPath, sourceMappingURLBase) { +function fromLocalWebpack(extensionPath) { const result = es.through(); const packagedDependencies = []; const packageJsonConfig = require(path.join(extensionPath, 'package.json')); @@ -77,9 +81,9 @@ function fromLocalWebpack(extensionPath, sourceMappingURLBase) { return data; })) .pipe(packageJsonFilter.restore); - const webpackStreams = webpackConfigLocations.map(webpackConfigPath => () => { + const webpackStreams = webpackConfigLocations.map(webpackConfigPath => { const webpackDone = (err, stats) => { - util.log(`Bundled extension: ${util.colors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`); + fancyLog(`Bundled extension: ${ansiColors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`); if (err) { result.emit('error', err); } @@ -103,22 +107,14 @@ function fromLocalWebpack(extensionPath, sourceMappingURLBase) { // source map handling: // * rewrite sourceMappingURL // * save to disk so that upload-task picks this up - if (sourceMappingURLBase) { - const contents = data.contents.toString('utf8'); - data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) { - return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`; - }), 'utf8'); - if (/\.js\.map$/.test(data.path)) { - if (!fs.existsSync(path.dirname(data.path))) { - fs.mkdirSync(path.dirname(data.path)); - } - fs.writeFileSync(data.path, data.contents); - } - } + const contents = data.contents.toString('utf8'); + data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) { + return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`; + }), 'utf8'); this.emit('data', data); })); }); - es.merge(sequence(webpackStreams), patchFilesStream) + es.merge(...webpackStreams, patchFilesStream) // .pipe(es.through(function (data) { // // debug // console.log('out', data.path, data.contents.length); @@ -157,7 +153,7 @@ const baseHeaders = { function fromMarketplace(extensionName, version, metadata) { const [publisher, name] = extensionName.split('.'); const url = `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher}/vsextensions/${name}/${version}/vspackage`; - util.log('Downloading extension:', util.colors.yellow(`${extensionName}@${version}`), '...'); + fancyLog('Downloading extension:', ansiColors.yellow(`${extensionName}@${version}`), '...'); const options = { base: url, requestOptions: { @@ -179,34 +175,12 @@ exports.fromMarketplace = fromMarketplace; const excludedExtensions = [ 'vscode-api-tests', 'vscode-colorize-tests', + 'vscode-test-resolver', 'ms-vscode.node-debug', 'ms-vscode.node-debug2', ]; const builtInExtensions = require('../builtInExtensions.json'); -/** - * We're doing way too much stuff at once, with webpack et al. So much stuff - * that while downloading extensions from the marketplace, node js doesn't get enough - * stack frames to complete the download in under 2 minutes, at which point the - * marketplace server cuts off the http request. So, we sequentialize the extensino tasks. - */ -function sequence(streamProviders) { - const result = es.through(); - function pop() { - if (streamProviders.length === 0) { - result.emit('end'); - } - else { - const fn = streamProviders.shift(); - fn() - .on('end', function () { setTimeout(pop, 0); }) - .pipe(result, { end: false }); - } - } - pop(); - return result; -} -function packageExtensionsStream(optsIn) { - const opts = optsIn || {}; +function packageLocalExtensionsStream() { const localExtensionDescriptions = glob.sync('extensions/*/package.json') .map(manifestPath => { const extensionPath = path.dirname(path.join(root, manifestPath)); @@ -214,21 +188,22 @@ function packageExtensionsStream(optsIn) { return { name: extensionName, path: extensionPath }; }) .filter(({ name }) => excludedExtensions.indexOf(name) === -1) - .filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true) .filter(({ name }) => builtInExtensions.every(b => b.name !== name)); - const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => { - return fromLocal(extension.path, opts.sourceMappingURLBase) - .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); - })]); - const localExtensionDependencies = () => gulp.src('extensions/node_modules/**', { base: '.' }); - const marketplaceExtensions = () => es.merge(...builtInExtensions - .filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true) - .map(extension => { + const nodeModules = gulp.src('extensions/node_modules/**', { base: '.' }); + const localExtensions = localExtensionDescriptions.map(extension => { + return fromLocal(extension.path) + .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); + }); + return es.merge(nodeModules, ...localExtensions) + .pipe(util2.setExecutableBit(['**/*.sh'])); +} +exports.packageLocalExtensionsStream = packageLocalExtensionsStream; +function packageMarketplaceExtensionsStream() { + const extensions = builtInExtensions.map(extension => { return fromMarketplace(extension.name, extension.version, extension.metadata) .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); - })); - return sequence([localExtensions, localExtensionDependencies, marketplaceExtensions]) - .pipe(util2.setExecutableBit(['**/*.sh'])) - .pipe(filter(['**', '!**/*.js.map'])); + }); + return es.merge(extensions) + .pipe(util2.setExecutableBit(['**/*.sh'])); } -exports.packageExtensionsStream = packageExtensionsStream; +exports.packageMarketplaceExtensionsStream = packageMarketplaceExtensionsStream; diff --git a/build/lib/extensions.ts b/build/lib/extensions.ts index 844b711a829..4b185aff681 100644 --- a/build/lib/extensions.ts +++ b/build/lib/extensions.ts @@ -13,28 +13,31 @@ import * as File from 'vinyl'; import * as vsce from 'vsce'; import { createStatsStream } from './stats'; import * as util2 from './util'; -import remote = require('gulp-remote-src'); +import remote = require('gulp-remote-retry-src'); const vzip = require('gulp-vinyl-zip'); import filter = require('gulp-filter'); import rename = require('gulp-rename'); -const util = require('gulp-util'); +import * as fancyLog from 'fancy-log'; +import * as ansiColors from 'ansi-colors'; const buffer = require('gulp-buffer'); import json = require('gulp-json-editor'); const webpack = require('webpack'); const webpackGulp = require('webpack-stream'); +const util = require('./util'); +const root = path.dirname(path.dirname(__dirname)); +const commit = util.getVersion(root); +const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`; -const root = path.resolve(path.join(__dirname, '..', '..')); - -function fromLocal(extensionPath: string, sourceMappingURLBase?: string): Stream { +function fromLocal(extensionPath: string): Stream { const webpackFilename = path.join(extensionPath, 'extension.webpack.config.js'); if (fs.existsSync(webpackFilename)) { - return fromLocalWebpack(extensionPath, sourceMappingURLBase); + return fromLocalWebpack(extensionPath); } else { return fromLocalNormal(extensionPath); } } -function fromLocalWebpack(extensionPath: string, sourceMappingURLBase: string | undefined): Stream { +function fromLocalWebpack(extensionPath: string): Stream { const result = es.through(); const packagedDependencies: string[] = []; @@ -90,10 +93,10 @@ function fromLocalWebpack(extensionPath: string, sourceMappingURLBase: string | .pipe(packageJsonFilter.restore); - const webpackStreams = webpackConfigLocations.map(webpackConfigPath => () => { + const webpackStreams = webpackConfigLocations.map(webpackConfigPath => { const webpackDone = (err: any, stats: any) => { - util.log(`Bundled extension: ${util.colors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`); + fancyLog(`Bundled extension: ${ansiColors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`); if (err) { result.emit('error', err); } @@ -122,24 +125,16 @@ function fromLocalWebpack(extensionPath: string, sourceMappingURLBase: string | // source map handling: // * rewrite sourceMappingURL // * save to disk so that upload-task picks this up - if (sourceMappingURLBase) { - const contents = (data.contents).toString('utf8'); - data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) { - return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`; - }), 'utf8'); + const contents = (data.contents).toString('utf8'); + data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) { + return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`; + }), 'utf8'); - if (/\.js\.map$/.test(data.path)) { - if (!fs.existsSync(path.dirname(data.path))) { - fs.mkdirSync(path.dirname(data.path)); - } - fs.writeFileSync(data.path, data.contents); - } - } this.emit('data', data); })); }); - es.merge(sequence(webpackStreams), patchFilesStream) + es.merge(...webpackStreams, patchFilesStream) // .pipe(es.through(function (data) { // // debug // console.log('out', data.path, data.contents.length); @@ -187,7 +182,7 @@ export function fromMarketplace(extensionName: string, version: string, metadata const [publisher, name] = extensionName.split('.'); const url = `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher}/vsextensions/${name}/${version}/vspackage`; - util.log('Downloading extension:', util.colors.yellow(`${extensionName}@${version}`), '...'); + fancyLog('Downloading extension:', ansiColors.yellow(`${extensionName}@${version}`), '...'); const options = { base: url, @@ -209,17 +204,10 @@ export function fromMarketplace(extensionName: string, version: string, metadata .pipe(packageJsonFilter.restore); } -interface IPackageExtensionsOptions { - /** - * Set to undefined to package all of them. - */ - desiredExtensions?: string[]; - sourceMappingURLBase?: string; -} - const excludedExtensions = [ 'vscode-api-tests', 'vscode-colorize-tests', + 'vscode-test-resolver', 'ms-vscode.node-debug', 'ms-vscode.node-debug2', ]; @@ -233,33 +221,7 @@ interface IBuiltInExtension { const builtInExtensions: IBuiltInExtension[] = require('../builtInExtensions.json'); -/** - * We're doing way too much stuff at once, with webpack et al. So much stuff - * that while downloading extensions from the marketplace, node js doesn't get enough - * stack frames to complete the download in under 2 minutes, at which point the - * marketplace server cuts off the http request. So, we sequentialize the extensino tasks. - */ -function sequence(streamProviders: { (): Stream }[]): Stream { - const result = es.through(); - - function pop() { - if (streamProviders.length === 0) { - result.emit('end'); - } else { - const fn = streamProviders.shift()!; - fn() - .on('end', function () { setTimeout(pop, 0); }) - .pipe(result, { end: false }); - } - } - - pop(); - return result; -} - -export function packageExtensionsStream(optsIn?: IPackageExtensionsOptions): NodeJS.ReadWriteStream { - const opts = optsIn || {}; - +export function packageLocalExtensionsStream(): NodeJS.ReadWriteStream { const localExtensionDescriptions = (glob.sync('extensions/*/package.json')) .map(manifestPath => { const extensionPath = path.dirname(path.join(root, manifestPath)); @@ -267,26 +229,24 @@ export function packageExtensionsStream(optsIn?: IPackageExtensionsOptions): Nod return { name: extensionName, path: extensionPath }; }) .filter(({ name }) => excludedExtensions.indexOf(name) === -1) - .filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true) .filter(({ name }) => builtInExtensions.every(b => b.name !== name)); - const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => { - return fromLocal(extension.path, opts.sourceMappingURLBase) + const nodeModules = gulp.src('extensions/node_modules/**', { base: '.' }); + const localExtensions = localExtensionDescriptions.map(extension => { + return fromLocal(extension.path) .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); - })]); + }); - const localExtensionDependencies = () => gulp.src('extensions/node_modules/**', { base: '.' }); - - const marketplaceExtensions = () => es.merge( - ...builtInExtensions - .filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true) - .map(extension => { - return fromMarketplace(extension.name, extension.version, extension.metadata) - .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); - }) - ); - - return sequence([localExtensions, localExtensionDependencies, marketplaceExtensions]) - .pipe(util2.setExecutableBit(['**/*.sh'])) - .pipe(filter(['**', '!**/*.js.map'])); + return es.merge(nodeModules, ...localExtensions) + .pipe(util2.setExecutableBit(['**/*.sh'])); +} + +export function packageMarketplaceExtensionsStream(): NodeJS.ReadWriteStream { + const extensions = builtInExtensions.map(extension => { + return fromMarketplace(extension.name, extension.version, extension.metadata) + .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); + }); + + return es.merge(extensions) + .pipe(util2.setExecutableBit(['**/*.sh'])); } diff --git a/build/lib/i18n.js b/build/lib/i18n.js index 1fc6b060e9c..c40b2988e28 100644 --- a/build/lib/i18n.js +++ b/build/lib/i18n.js @@ -13,15 +13,16 @@ const xml2js = require("xml2js"); const glob = require("glob"); const https = require("https"); const gulp = require("gulp"); -const util = require("gulp-util"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); const iconv = require("iconv-lite"); const NUMBER_OF_CONCURRENT_DOWNLOADS = 4; function log(message, ...rest) { - util.log(util.colors.green('[i18n]'), message, ...rest); + fancyLog(ansiColors.green('[i18n]'), message, ...rest); } exports.defaultLanguages = [ - { id: 'zh-tw', folderName: 'cht', transifexId: 'zh-hant' }, - { id: 'zh-cn', folderName: 'chs', transifexId: 'zh-hans' }, + { id: 'zh-tw', folderName: 'cht', translationId: 'zh-hant' }, + { id: 'zh-cn', folderName: 'chs', translationId: 'zh-hans' }, { id: 'ja', folderName: 'jpn' }, { id: 'ko', folderName: 'kor' }, { id: 'de', folderName: 'deu' }, @@ -371,7 +372,11 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { } }); }); - let languageDirectory = path.join(__dirname, '..', '..', 'i18n'); + let languageDirectory = path.join(__dirname, '..', '..', '..', 'vscode-loc', 'i18n'); + if (!fs.existsSync(languageDirectory)) { + log(`No VS Code localization repository found. Looking at ${languageDirectory}`); + log(`To bundle translations please check out the vscode-loc repository as a sibling of the vscode repository.`); + } let sortedLanguages = sortLanguages(languages); sortedLanguages.forEach((language) => { if (process.env['VSCODE_BUILD_VERBOSE']) { @@ -379,22 +384,25 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { } statistics[language.id] = 0; let localizedModules = Object.create(null); - let languageFolderName = language.folderName || language.id; - let cwd = path.join(languageDirectory, languageFolderName, 'src'); + let languageFolderName = language.translationId || language.id; + let i18nFile = path.join(languageDirectory, `vscode-language-pack-${languageFolderName}`, 'translations', 'main.i18n.json'); + let allMessages; + if (fs.existsSync(i18nFile)) { + let content = stripComments(fs.readFileSync(i18nFile, 'utf8')); + allMessages = JSON.parse(content); + } modules.forEach((module) => { let order = keysSection[module]; - let i18nFile = path.join(cwd, module) + '.i18n.json'; - let messages = null; - if (fs.existsSync(i18nFile)) { - let content = stripComments(fs.readFileSync(i18nFile, 'utf8')); - messages = JSON.parse(content); + let moduleMessage; + if (allMessages) { + moduleMessage = allMessages.contents[module]; } - else { + if (!moduleMessage) { if (process.env['VSCODE_BUILD_VERBOSE']) { log(`No localized messages found for module ${module}. Using default messages.`); } - messages = defaultMessages[module]; - statistics[language.id] = statistics[language.id] + Object.keys(messages).length; + moduleMessage = defaultMessages[module]; + statistics[language.id] = statistics[language.id] + Object.keys(moduleMessage).length; } let localizedMessages = []; order.forEach((keyInfo) => { @@ -405,7 +413,7 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { else { key = keyInfo.key; } - let message = messages[key]; + let message = moduleMessage[key]; if (!message) { if (process.env['VSCODE_BUILD_VERBOSE']) { log(`No localized message found for key ${key} in module ${module}. Using default message.`); @@ -488,7 +496,7 @@ function getResource(sourceFile) { else if (/^vs\/code/.test(sourceFile)) { return { name: 'vs/code', project: workbenchProject }; } - else if (/^vs\/workbench\/parts/.test(sourceFile)) { + else if (/^vs\/workbench\/contrib/.test(sourceFile)) { resource = sourceFile.split('/', 4).join('/'); return { name: resource, project: workbenchProject }; } @@ -572,7 +580,7 @@ function createXlfFilesForExtensions() { } return _xlf; } - gulp.src([`./extensions/${extensionName}/package.nls.json`, `./extensions/${extensionName}/**/nls.metadata.json`]).pipe(event_stream_1.through(function (file) { + gulp.src([`./extensions/${extensionName}/package.nls.json`, `./extensions/${extensionName}/**/nls.metadata.json`], { allowEmpty: true }).pipe(event_stream_1.through(function (file) { if (file.isBuffer()) { const buffer = file.contents; const basename = path.basename(file.path); @@ -949,7 +957,7 @@ function retrieveResource(language, resource, apiHostname, credentials) { return limiter.queue(() => new Promise((resolve, reject) => { const slug = resource.name.replace(/\//g, '_'); const project = resource.project; - let transifexLanguageId = language.id === 'ps' ? 'en' : language.transifexId || language.id; + let transifexLanguageId = language.id === 'ps' ? 'en' : language.translationId || language.id; const options = { hostname: apiHostname, path: `/api/2/project/${project}/resource/${slug}/translation/${transifexLanguageId}?file&mode=onlyreviewed`, @@ -1032,7 +1040,7 @@ function prepareI18nPackFiles(externalExtensions, resultingTranslationPaths, pse let extensionsPacks = {}; let errors = []; return event_stream_1.through(function (xlf) { - let project = path.dirname(xlf.relative); + let project = path.basename(path.dirname(xlf.relative)); let resource = path.basename(xlf.relative, '.xlf'); let contents = xlf.contents.toString(); let parsePromise = pseudo ? XLF.parsePseudo(contents) : XLF.parse(contents); diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index 296d1286fbb..32b0e6fb4c7 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -27,135 +27,155 @@ "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/cli", + "name": "vs/workbench/api/common", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/codeEditor", + "name": "vs/workbench/contrib/cli", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/comments", + "name": "vs/workbench/contrib/codeEditor", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/debug", + "name": "vs/workbench/contrib/callHierarchy", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/emmet", + "name": "vs/workbench/contrib/comments", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/execution", + "name": "vs/workbench/contrib/debug", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/extensions", + "name": "vs/workbench/contrib/emmet", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/feedback", + "name": "vs/workbench/contrib/extensions", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/files", + "name": "vs/workbench/contrib/externalTerminal", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/html", + "name": "vs/workbench/contrib/feedback", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/markers", + "name": "vs/workbench/contrib/files", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/localizations", + "name": "vs/workbench/contrib/html", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/logs", + "name": "vs/workbench/contrib/issue", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/output", + "name": "vs/workbench/contrib/markers", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/performance", + "name": "vs/workbench/contrib/localizations", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/preferences", + "name": "vs/workbench/contrib/logs", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/quickopen", + "name": "vs/workbench/contrib/output", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/relauncher", + "name": "vs/workbench/contrib/performance", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/scm", + "name": "vs/workbench/contrib/preferences", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/search", + "name": "vs/workbench/contrib/quickopen", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/snippets", + "name": "vs/workbench/contrib/remote", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/stats", + "name": "vs/workbench/contrib/relauncher", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/surveys", + "name": "vs/workbench/contrib/scm", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/tasks", + "name": "vs/workbench/contrib/search", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/terminal", + "name": "vs/workbench/contrib/snippets", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/themes", + "name": "vs/workbench/contrib/format", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/trust", + "name": "vs/workbench/contrib/stats", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/update", + "name": "vs/workbench/contrib/surveys", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/url", + "name": "vs/workbench/contrib/tasks", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/watermark", + "name": "vs/workbench/contrib/terminal", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/webview", + "name": "vs/workbench/contrib/themes", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/welcome", + "name": "vs/workbench/contrib/trust", "project": "vscode-workbench" }, { - "name": "vs/workbench/parts/outline", + "name": "vs/workbench/contrib/update", + "project": "vscode-workbench" + }, + { + "name": "vs/workbench/contrib/url", + "project": "vscode-workbench" + }, + { + "name": "vs/workbench/contrib/watermark", + "project": "vscode-workbench" + }, + { + "name": "vs/workbench/contrib/webview", + "project": "vscode-workbench" + }, + { + "name": "vs/workbench/contrib/welcome", + "project": "vscode-workbench" + }, + { + "name": "vs/workbench/contrib/outline", "project": "vscode-workbench" }, { @@ -195,13 +215,17 @@ "project": "vscode-workbench" }, { - "name": "vs/workbench/services/jsonschemas", + "name": "vs/workbench/services/extensionManagement", "project": "vscode-workbench" }, { "name": "vs/workbench/services/files", "project": "vscode-workbench" }, + { + "name": "vs/workbench/services/integrity", + "project": "vscode-workbench" + }, { "name": "vs/workbench/services/keybinding", "project": "vscode-workbench" @@ -238,6 +262,10 @@ "name": "vs/workbench/services/decorations", "project": "vscode-workbench" }, + { + "name": "vs/workbench/services/label", + "project": "vscode-workbench" + }, { "name": "vs/workbench/services/preferences", "project": "vscode-preferences" diff --git a/build/lib/i18n.ts b/build/lib/i18n.ts index 81ba0c0939e..9f53df17bad 100644 --- a/build/lib/i18n.ts +++ b/build/lib/i18n.ts @@ -13,19 +13,19 @@ import * as xml2js from 'xml2js'; import * as glob from 'glob'; import * as https from 'https'; import * as gulp from 'gulp'; - -import * as util from 'gulp-util'; +import * as fancyLog from 'fancy-log'; +import * as ansiColors from 'ansi-colors'; import * as iconv from 'iconv-lite'; const NUMBER_OF_CONCURRENT_DOWNLOADS = 4; function log(message: any, ...rest: any[]): void { - util.log(util.colors.green('[i18n]'), message, ...rest); + fancyLog(ansiColors.green('[i18n]'), message, ...rest); } export interface Language { - id: string; // laguage id, e.g. zh-tw, de - transifexId?: string; // language id used in transifex, e.g zh-hant, de (optional, if not set, the id is used) + id: string; // language id, e.g. zh-tw, de + translationId?: string; // language id used in translation tools, e.g. zh-hant, de (optional, if not set, the id is used) folderName?: string; // language specific folder name, e.g. cht, deu (optional, if not set, the id is used) } @@ -38,8 +38,8 @@ export interface InnoSetup { } export const defaultLanguages: Language[] = [ - { id: 'zh-tw', folderName: 'cht', transifexId: 'zh-hant' }, - { id: 'zh-cn', folderName: 'chs', transifexId: 'zh-hans' }, + { id: 'zh-tw', folderName: 'cht', translationId: 'zh-hant' }, + { id: 'zh-cn', folderName: 'chs', translationId: 'zh-hans' }, { id: 'ja', folderName: 'jpn' }, { id: 'ko', folderName: 'kor' }, { id: 'de', folderName: 'deu' }, @@ -144,6 +144,15 @@ interface BundledExtensionFormat { }; } +interface I18nFormat { + version: string; + contents: { + [module: string]: { + [messageKey: string]: string; + }; + }; +} + export class Line { private buffer: string[] = []; @@ -486,7 +495,11 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json }); }); - let languageDirectory = path.join(__dirname, '..', '..', 'i18n'); + let languageDirectory = path.join(__dirname, '..', '..', '..', 'vscode-loc', 'i18n'); + if (!fs.existsSync(languageDirectory)) { + log(`No VS Code localization repository found. Looking at ${languageDirectory}`); + log(`To bundle translations please check out the vscode-loc repository as a sibling of the vscode repository.`); + } let sortedLanguages = sortLanguages(languages); sortedLanguages.forEach((language) => { if (process.env['VSCODE_BUILD_VERBOSE']) { @@ -495,21 +508,25 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json statistics[language.id] = 0; let localizedModules: Map = Object.create(null); - let languageFolderName = language.folderName || language.id; - let cwd = path.join(languageDirectory, languageFolderName, 'src'); + let languageFolderName = language.translationId || language.id; + let i18nFile = path.join(languageDirectory, `vscode-language-pack-${languageFolderName}`, 'translations', 'main.i18n.json'); + let allMessages: I18nFormat | undefined; + if (fs.existsSync(i18nFile)) { + let content = stripComments(fs.readFileSync(i18nFile, 'utf8')); + allMessages = JSON.parse(content); + } modules.forEach((module) => { let order = keysSection[module]; - let i18nFile = path.join(cwd, module) + '.i18n.json'; - let messages: Map | null = null; - if (fs.existsSync(i18nFile)) { - let content = stripComments(fs.readFileSync(i18nFile, 'utf8')); - messages = JSON.parse(content); - } else { + let moduleMessage: { [messageKey: string]: string } | undefined; + if (allMessages) { + moduleMessage = allMessages.contents[module]; + } + if (!moduleMessage) { if (process.env['VSCODE_BUILD_VERBOSE']) { log(`No localized messages found for module ${module}. Using default messages.`); } - messages = defaultMessages[module]; - statistics[language.id] = statistics[language.id] + Object.keys(messages).length; + moduleMessage = defaultMessages[module]; + statistics[language.id] = statistics[language.id] + Object.keys(moduleMessage).length; } let localizedMessages: string[] = []; order.forEach((keyInfo) => { @@ -519,7 +536,7 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json } else { key = keyInfo.key; } - let message: string = messages![key]; + let message: string = moduleMessage![key]; if (!message) { if (process.env['VSCODE_BUILD_VERBOSE']) { log(`No localized message found for key ${key} in module ${module}. Using default message.`); @@ -602,7 +619,7 @@ export function getResource(sourceFile: string): Resource { return { name: 'vs/base', project: editorProject }; } else if (/^vs\/code/.test(sourceFile)) { return { name: 'vs/code', project: workbenchProject }; - } else if (/^vs\/workbench\/parts/.test(sourceFile)) { + } else if (/^vs\/workbench\/contrib/.test(sourceFile)) { resource = sourceFile.split('/', 4).join('/'); return { name: resource, project: workbenchProject }; } else if (/^vs\/workbench\/services/.test(sourceFile)) { @@ -684,7 +701,7 @@ export function createXlfFilesForExtensions(): ThroughStream { } return _xlf; } - gulp.src([`./extensions/${extensionName}/package.nls.json`, `./extensions/${extensionName}/**/nls.metadata.json`]).pipe(through(function (file: File) { + gulp.src([`./extensions/${extensionName}/package.nls.json`, `./extensions/${extensionName}/**/nls.metadata.json`], { allowEmpty: true }).pipe(through(function (file: File) { if (file.isBuffer()) { const buffer: Buffer = file.contents as Buffer; const basename = path.basename(file.path); @@ -1085,7 +1102,7 @@ function retrieveResource(language: Language, resource: Resource, apiHostname: s return limiter.queue(() => new Promise((resolve, reject) => { const slug = resource.name.replace(/\//g, '_'); const project = resource.project; - let transifexLanguageId = language.id === 'ps' ? 'en' : language.transifexId || language.id; + let transifexLanguageId = language.id === 'ps' ? 'en' : language.translationId || language.id; const options = { hostname: apiHostname, path: `/api/2/project/${project}/resource/${slug}/translation/${transifexLanguageId}?file&mode=onlyreviewed`, @@ -1186,7 +1203,7 @@ export function prepareI18nPackFiles(externalExtensions: Map, resultingT let extensionsPacks: Map = {}; let errors: any[] = []; return through(function (this: ThroughStream, xlf: File) { - let project = path.dirname(xlf.relative); + let project = path.basename(path.dirname(xlf.relative)); let resource = path.basename(xlf.relative, '.xlf'); let contents = xlf.contents.toString(); let parsePromise = pseudo ? XLF.parsePseudo(contents) : XLF.parse(contents); @@ -1353,4 +1370,4 @@ function decodeEntities(value: string): string { function pseudify(message: string) { return '\uFF3B' + message.replace(/[aouei]/g, '$&$&') + '\uFF3D'; -} \ No newline at end of file +} diff --git a/build/lib/node.js b/build/lib/node.js new file mode 100644 index 00000000000..403ae3d9657 --- /dev/null +++ b/build/lib/node.js @@ -0,0 +1,15 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +const path = require("path"); +const fs = require("fs"); +const root = path.dirname(path.dirname(__dirname)); +const yarnrcPath = path.join(root, 'remote', '.yarnrc'); +const yarnrc = fs.readFileSync(yarnrcPath, 'utf8'); +const version = /^target\s+"([^"]+)"$/m.exec(yarnrc)[1]; +const node = process.platform === 'win32' ? 'node.exe' : 'node'; +const nodePath = path.join(root, '.build', 'node', `v${version}`, `${process.platform}-${process.arch}`, node); +console.log(nodePath); diff --git a/build/lib/node.ts b/build/lib/node.ts new file mode 100644 index 00000000000..64397034461 --- /dev/null +++ b/build/lib/node.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from 'path'; +import * as fs from 'fs'; + +const root = path.dirname(path.dirname(__dirname)); +const yarnrcPath = path.join(root, 'remote', '.yarnrc'); +const yarnrc = fs.readFileSync(yarnrcPath, 'utf8'); +const version = /^target\s+"([^"]+)"$/m.exec(yarnrc)![1]; +const node = process.platform === 'win32' ? 'node.exe' : 'node'; +const nodePath = path.join(root, '.build', 'node', `v${version}`, `${process.platform}-${process.arch}`, node); + +console.log(nodePath); \ No newline at end of file diff --git a/build/lib/optimize.js b/build/lib/optimize.js index 07cdebe30ee..2b59d926838 100644 --- a/build/lib/optimize.js +++ b/build/lib/optimize.js @@ -13,7 +13,8 @@ const flatmap = require("gulp-flatmap"); const sourcemaps = require("gulp-sourcemaps"); const uglify = require("gulp-uglify"); const composer = require("gulp-uglify/composer"); -const gulpUtil = require("gulp-util"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); const path = require("path"); const pump = require("pump"); const uglifyes = require("uglify-es"); @@ -24,7 +25,7 @@ const stats_1 = require("./stats"); const util = require("./util"); const REPO_ROOT_PATH = path.join(__dirname, '../..'); function log(prefix, message) { - gulpUtil.log(gulpUtil.colors.cyan('[' + prefix + ']'), message); + fancyLog(ansiColors.cyan('[' + prefix + ']'), message); } function loaderConfig(emptyPaths) { const result = { @@ -110,13 +111,17 @@ function toBundleStream(src, bundledFileHeader, bundles) { return toConcatStream(src, bundledFileHeader, bundle.sources, bundle.dest); })); } +const DEFAULT_FILE_HEADER = [ + '/*!--------------------------------------------------------', + ' * Copyright (C) Microsoft Corporation. All rights reserved.', + ' *--------------------------------------------------------*/' +].join('\n'); function optimizeTask(opts) { const src = opts.src; const entryPoints = opts.entryPoints; - const otherSources = opts.otherSources; const resources = opts.resources; const loaderConfig = opts.loaderConfig; - const bundledFileHeader = opts.header; + const bundledFileHeader = opts.header || DEFAULT_FILE_HEADER; const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader); const out = opts.out; return function () { @@ -136,7 +141,7 @@ function optimizeTask(opts) { } filteredResources.push('!' + resource); }); - gulp.src(filteredResources, { base: `${src}` }).pipe(resourcesStream); + gulp.src(filteredResources, { base: `${src}`, allowEmpty: true }).pipe(resourcesStream); const bundleInfoArray = []; if (opts.bundleInfo) { bundleInfoArray.push(new VinylFile({ @@ -147,20 +152,7 @@ function optimizeTask(opts) { } es.readArray(bundleInfoArray).pipe(bundleInfoStream); }); - const otherSourcesStream = es.through(); - const otherSourcesStreamArr = []; - gulp.src(otherSources, { base: `${src}` }) - .pipe(es.through(function (data) { - otherSourcesStreamArr.push(toConcatStream(src, bundledFileHeader, [data], data.relative)); - }, function () { - if (!otherSourcesStreamArr.length) { - setTimeout(function () { otherSourcesStream.emit('end'); }, 0); - } - else { - es.merge(otherSourcesStreamArr).pipe(otherSourcesStream); - } - })); - const result = es.merge(loader(src, bundledFileHeader, bundleLoader), bundlesStream, otherSourcesStream, resourcesStream, bundleInfoStream); + const result = es.merge(loader(src, bundledFileHeader, bundleLoader), bundlesStream, resourcesStream, bundleInfoStream); return result .pipe(sourcemaps.write('./', { sourceRoot: undefined, @@ -223,7 +215,12 @@ function minifyTask(src, sourceMapBaseUrl) { return cb => { const jsFilter = filter('**/*.js', { restore: true }); const cssFilter = filter('**/*.css', { restore: true }); - pump(gulp.src([src + '/**', '!' + src + '/**/*.map']), jsFilter, sourcemaps.init({ loadMaps: true }), uglifyWithCopyrights(), jsFilter.restore, cssFilter, minifyCSS({ reduceIdents: false }), cssFilter.restore, sourcemaps.write('./', { + pump(gulp.src([src + '/**', '!' + src + '/**/*.map']), jsFilter, sourcemaps.init({ loadMaps: true }), uglifyWithCopyrights(), jsFilter.restore, cssFilter, minifyCSS({ reduceIdents: false }), cssFilter.restore, sourcemaps.mapSources((sourcePath) => { + if (sourcePath === 'bootstrap-fork.js') { + return 'bootstrap-fork.orig.js'; + } + return sourcePath; + }), sourcemaps.write('./', { sourceMappingURL, sourceRoot: undefined, includeContent: true, diff --git a/build/lib/optimize.ts b/build/lib/optimize.ts index 85d15b23543..6bf1233c303 100644 --- a/build/lib/optimize.ts +++ b/build/lib/optimize.ts @@ -14,7 +14,8 @@ import * as flatmap from 'gulp-flatmap'; import * as sourcemaps from 'gulp-sourcemaps'; import * as uglify from 'gulp-uglify'; import * as composer from 'gulp-uglify/composer'; -import * as gulpUtil from 'gulp-util'; +import * as fancyLog from 'fancy-log'; +import * as ansiColors from 'ansi-colors'; import * as path from 'path'; import * as pump from 'pump'; import * as sm from 'source-map'; @@ -28,7 +29,7 @@ import * as util from './util'; const REPO_ROOT_PATH = path.join(__dirname, '../..'); function log(prefix: string, message: string): void { - gulpUtil.log(gulpUtil.colors.cyan('[' + prefix + ']'), message); + fancyLog(ansiColors.cyan('[' + prefix + ']'), message); } export function loaderConfig(emptyPaths?: string[]) { @@ -141,10 +142,6 @@ export interface IOptimizeTaskOpts { * (for AMD files, will get bundled and get Copyright treatment) */ entryPoints: bundle.IEntryPoint[]; - /** - * (for non-AMD files that should get Copyright treatment) - */ - otherSources: string[]; /** * (svg, etc.) */ @@ -157,7 +154,7 @@ export interface IOptimizeTaskOpts { /** * (basically the Copyright treatment) */ - header: string; + header?: string; /** * (emit bundleInfo.json file) */ @@ -172,13 +169,18 @@ export interface IOptimizeTaskOpts { languages?: Language[]; } +const DEFAULT_FILE_HEADER = [ + '/*!--------------------------------------------------------', + ' * Copyright (C) Microsoft Corporation. All rights reserved.', + ' *--------------------------------------------------------*/' +].join('\n'); + export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStream { const src = opts.src; const entryPoints = opts.entryPoints; - const otherSources = opts.otherSources; const resources = opts.resources; const loaderConfig = opts.loaderConfig; - const bundledFileHeader = opts.header; + const bundledFileHeader = opts.header || DEFAULT_FILE_HEADER; const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader); const out = opts.out; @@ -200,7 +202,7 @@ export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStr } filteredResources.push('!' + resource); }); - gulp.src(filteredResources, { base: `${src}` }).pipe(resourcesStream); + gulp.src(filteredResources, { base: `${src}`, allowEmpty: true }).pipe(resourcesStream); const bundleInfoArray: VinylFile[] = []; if (opts.bundleInfo) { @@ -213,24 +215,9 @@ export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStr es.readArray(bundleInfoArray).pipe(bundleInfoStream); }); - const otherSourcesStream = es.through(); - const otherSourcesStreamArr: NodeJS.ReadWriteStream[] = []; - - gulp.src(otherSources, { base: `${src}` }) - .pipe(es.through(function (data) { - otherSourcesStreamArr.push(toConcatStream(src, bundledFileHeader, [data], data.relative)); - }, function () { - if (!otherSourcesStreamArr.length) { - setTimeout(function () { otherSourcesStream.emit('end'); }, 0); - } else { - es.merge(otherSourcesStreamArr).pipe(otherSourcesStream); - } - })); - const result = es.merge( loader(src, bundledFileHeader, bundleLoader), bundlesStream, - otherSourcesStream, resourcesStream, bundleInfoStream ); @@ -317,6 +304,13 @@ export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => cssFilter, minifyCSS({ reduceIdents: false }), cssFilter.restore, + (sourcemaps).mapSources((sourcePath: string) => { + if (sourcePath === 'bootstrap-fork.js') { + return 'bootstrap-fork.orig.js'; + } + + return sourcePath; + }), sourcemaps.write('./', { sourceMappingURL, sourceRoot: undefined, diff --git a/build/lib/reporter.js b/build/lib/reporter.js index 598aabec244..e0461dc6d9d 100644 --- a/build/lib/reporter.js +++ b/build/lib/reporter.js @@ -6,7 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); const es = require("event-stream"); const _ = require("underscore"); -const util = require("gulp-util"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); const fs = require("fs"); const path = require("path"); const allErrors = []; @@ -17,7 +18,7 @@ function onStart() { return; } startTime = new Date().getTime(); - util.log(`Starting ${util.colors.green('compilation')}...`); + fancyLog(`Starting ${ansiColors.green('compilation')}...`); } function onEnd() { if (--count > 0) { @@ -38,7 +39,7 @@ function log() { errors.map(err => { if (!seen.has(err)) { seen.add(err); - util.log(`${util.colors.red('Error')}: ${err}`); + fancyLog(`${ansiColors.red('Error')}: ${err}`); } }); const regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/; @@ -53,7 +54,7 @@ function log() { catch (err) { //noop } - util.log(`Finished ${util.colors.green('compilation')} with ${errors.length} errors after ${util.colors.magenta((new Date().getTime() - startTime) + ' ms')}`); + fancyLog(`Finished ${ansiColors.green('compilation')} with ${errors.length} errors after ${ansiColors.magenta((new Date().getTime() - startTime) + ' ms')}`); } function createReporter() { const errors = []; diff --git a/build/lib/reporter.ts b/build/lib/reporter.ts index 68e037e9224..ec908817518 100644 --- a/build/lib/reporter.ts +++ b/build/lib/reporter.ts @@ -7,7 +7,8 @@ import * as es from 'event-stream'; import * as _ from 'underscore'; -import * as util from 'gulp-util'; +import * as fancyLog from 'fancy-log'; +import * as ansiColors from 'ansi-colors'; import * as fs from 'fs'; import * as path from 'path'; @@ -21,7 +22,7 @@ function onStart(): void { } startTime = new Date().getTime(); - util.log(`Starting ${util.colors.green('compilation')}...`); + fancyLog(`Starting ${ansiColors.green('compilation')}...`); } function onEnd(): void { @@ -47,7 +48,7 @@ function log(): void { errors.map(err => { if (!seen.has(err)) { seen.add(err); - util.log(`${util.colors.red('Error')}: ${err}`); + fancyLog(`${ansiColors.red('Error')}: ${err}`); } }); @@ -65,7 +66,7 @@ function log(): void { //noop } - util.log(`Finished ${util.colors.green('compilation')} with ${errors.length} errors after ${util.colors.magenta((new Date().getTime() - startTime!) + ' ms')}`); + fancyLog(`Finished ${ansiColors.green('compilation')} with ${errors.length} errors after ${ansiColors.magenta((new Date().getTime() - startTime!) + ' ms')}`); } export interface IReporter { diff --git a/build/lib/standalone.js b/build/lib/standalone.js index cf921e7401c..7e363da0948 100644 --- a/build/lib/standalone.js +++ b/build/lib/standalone.js @@ -27,23 +27,23 @@ function writeFile(filePath, contents) { fs.writeFileSync(filePath, contents); } function extractEditor(options) { - const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString()); + const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.monaco.json')).toString()); let compilerOptions; if (tsConfig.extends) { compilerOptions = Object.assign({}, require(path.join(options.sourcesRoot, tsConfig.extends)).compilerOptions, tsConfig.compilerOptions); + delete tsConfig.extends; } else { compilerOptions = tsConfig.compilerOptions; } tsConfig.compilerOptions = compilerOptions; + compilerOptions.noEmit = false; compilerOptions.noUnusedLocals = false; compilerOptions.preserveConstEnums = false; compilerOptions.declaration = false; compilerOptions.moduleResolution = ts.ModuleResolutionKind.Classic; - delete compilerOptions.types; - delete tsConfig.extends; - tsConfig.exclude = []; options.compilerOptions = compilerOptions; + console.log(`Running with shakeLevel ${tss.toStringShakeLevel(options.shakeLevel)}`); let result = tss.shake(options); for (let fileName in result) { if (result.hasOwnProperty(fileName)) { diff --git a/build/lib/standalone.ts b/build/lib/standalone.ts index b7b0fee295f..6a4cdbf7718 100644 --- a/build/lib/standalone.ts +++ b/build/lib/standalone.ts @@ -31,26 +31,27 @@ function writeFile(filePath: string, contents: Buffer | string): void { } export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: string }): void { - const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString()); + const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.monaco.json')).toString()); let compilerOptions: { [key: string]: any }; if (tsConfig.extends) { compilerOptions = Object.assign({}, require(path.join(options.sourcesRoot, tsConfig.extends)).compilerOptions, tsConfig.compilerOptions); + delete tsConfig.extends; } else { compilerOptions = tsConfig.compilerOptions; } tsConfig.compilerOptions = compilerOptions; + compilerOptions.noEmit = false; compilerOptions.noUnusedLocals = false; compilerOptions.preserveConstEnums = false; compilerOptions.declaration = false; compilerOptions.moduleResolution = ts.ModuleResolutionKind.Classic; - delete compilerOptions.types; - delete tsConfig.extends; - tsConfig.exclude = []; options.compilerOptions = compilerOptions; + console.log(`Running with shakeLevel ${tss.toStringShakeLevel(options.shakeLevel)}`); + let result = tss.shake(options); for (let fileName in result) { if (result.hasOwnProperty(fileName)) { diff --git a/build/lib/stats.js b/build/lib/stats.js index c08cd57b3bc..99ad665f223 100644 --- a/build/lib/stats.js +++ b/build/lib/stats.js @@ -5,7 +5,8 @@ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); const es = require("event-stream"); -const util = require("gulp-util"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); const appInsights = require("applicationinsights"); class Entry { constructor(name, totalCount, totalSize) { @@ -24,13 +25,13 @@ class Entry { } else { if (this.totalCount === 1) { - return `Stats for '${util.colors.grey(this.name)}': ${Math.round(this.totalSize / 1204)}KB`; + return `Stats for '${ansiColors.grey(this.name)}': ${Math.round(this.totalSize / 1204)}KB`; } else { const count = this.totalCount < 100 - ? util.colors.green(this.totalCount.toString()) - : util.colors.red(this.totalCount.toString()); - return `Stats for '${util.colors.grey(this.name)}': ${count} files, ${Math.round(this.totalSize / 1204)}KB`; + ? ansiColors.green(this.totalCount.toString()) + : ansiColors.red(this.totalCount.toString()); + return `Stats for '${ansiColors.grey(this.name)}': ${count} files, ${Math.round(this.totalSize / 1204)}KB`; } } } @@ -57,13 +58,13 @@ function createStatsStream(group, log) { }, function () { if (log) { if (entry.totalCount === 1) { - util.log(`Stats for '${util.colors.grey(entry.name)}': ${Math.round(entry.totalSize / 1204)}KB`); + fancyLog(`Stats for '${ansiColors.grey(entry.name)}': ${Math.round(entry.totalSize / 1204)}KB`); } else { const count = entry.totalCount < 100 - ? util.colors.green(entry.totalCount.toString()) - : util.colors.red(entry.totalCount.toString()); - util.log(`Stats for '${util.colors.grey(entry.name)}': ${count} files, ${Math.round(entry.totalSize / 1204)}KB`); + ? ansiColors.green(entry.totalCount.toString()) + : ansiColors.red(entry.totalCount.toString()); + fancyLog(`Stats for '${ansiColors.grey(entry.name)}': ${count} files, ${Math.round(entry.totalSize / 1204)}KB`); } } this.emit('end'); diff --git a/build/lib/stats.ts b/build/lib/stats.ts index 7f5548dc1c4..a94b1c9ae1a 100644 --- a/build/lib/stats.ts +++ b/build/lib/stats.ts @@ -6,7 +6,8 @@ 'use strict'; import * as es from 'event-stream'; -import * as util from 'gulp-util'; +import * as fancyLog from 'fancy-log'; +import * as ansiColors from 'ansi-colors'; import * as File from 'vinyl'; import * as appInsights from 'applicationinsights'; @@ -22,14 +23,14 @@ class Entry { } } else { if (this.totalCount === 1) { - return `Stats for '${util.colors.grey(this.name)}': ${Math.round(this.totalSize / 1204)}KB`; + return `Stats for '${ansiColors.grey(this.name)}': ${Math.round(this.totalSize / 1204)}KB`; } else { const count = this.totalCount < 100 - ? util.colors.green(this.totalCount.toString()) - : util.colors.red(this.totalCount.toString()); + ? ansiColors.green(this.totalCount.toString()) + : ansiColors.red(this.totalCount.toString()); - return `Stats for '${util.colors.grey(this.name)}': ${count} files, ${Math.round(this.totalSize / 1204)}KB`; + return `Stats for '${ansiColors.grey(this.name)}': ${count} files, ${Math.round(this.totalSize / 1204)}KB`; } } } @@ -58,14 +59,14 @@ export function createStatsStream(group: string, log?: boolean): es.ThroughStrea }, function () { if (log) { if (entry.totalCount === 1) { - util.log(`Stats for '${util.colors.grey(entry.name)}': ${Math.round(entry.totalSize / 1204)}KB`); + fancyLog(`Stats for '${ansiColors.grey(entry.name)}': ${Math.round(entry.totalSize / 1204)}KB`); } else { const count = entry.totalCount < 100 - ? util.colors.green(entry.totalCount.toString()) - : util.colors.red(entry.totalCount.toString()); + ? ansiColors.green(entry.totalCount.toString()) + : ansiColors.red(entry.totalCount.toString()); - util.log(`Stats for '${util.colors.grey(entry.name)}': ${count} files, ${Math.round(entry.totalSize / 1204)}KB`); + fancyLog(`Stats for '${ansiColors.grey(entry.name)}': ${count} files, ${Math.round(entry.totalSize / 1204)}KB`); } } diff --git a/build/lib/task.js b/build/lib/task.js new file mode 100644 index 00000000000..f1e6e3f6245 --- /dev/null +++ b/build/lib/task.js @@ -0,0 +1,96 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); +function _isPromise(p) { + if (typeof p.then === 'function') { + return true; + } + return false; +} +function _renderTime(time) { + return `${Math.round(time)} ms`; +} +async function _execute(task) { + const name = task.taskName || task.displayName || ``; + if (!task._tasks) { + fancyLog('Starting', ansiColors.cyan(name), '...'); + } + const startTime = process.hrtime(); + await _doExecute(task); + const elapsedArr = process.hrtime(startTime); + const elapsedNanoseconds = (elapsedArr[0] * 1e9 + elapsedArr[1]); + if (!task._tasks) { + fancyLog(`Finished`, ansiColors.cyan(name), 'after', ansiColors.magenta(_renderTime(elapsedNanoseconds / 1e6))); + } +} +async function _doExecute(task) { + // Always invoke as if it were a callback task + return new Promise((resolve, reject) => { + if (task.length === 1) { + // this is a callback task + task((err) => { + if (err) { + return reject(err); + } + resolve(); + }); + return; + } + const taskResult = task(); + if (typeof taskResult === 'undefined') { + // this is a sync task + resolve(); + return; + } + if (_isPromise(taskResult)) { + // this is a promise returning task + taskResult.then(resolve, reject); + return; + } + // this is a stream returning task + taskResult.on('end', _ => resolve()); + taskResult.on('error', err => reject(err)); + }); +} +function series(...tasks) { + const result = async () => { + for (let i = 0; i < tasks.length; i++) { + await _execute(tasks[i]); + } + }; + result._tasks = tasks; + return result; +} +exports.series = series; +function parallel(...tasks) { + const result = async () => { + await Promise.all(tasks.map(t => _execute(t))); + }; + result._tasks = tasks; + return result; +} +exports.parallel = parallel; +function define(name, task) { + if (task._tasks) { + // This is a composite task + const lastTask = task._tasks[task._tasks.length - 1]; + if (lastTask._tasks || lastTask.taskName) { + // This is a composite task without a real task function + // => generate a fake task function + return define(name, series(task, () => Promise.resolve())); + } + lastTask.taskName = name; + task.displayName = name; + return task; + } + // This is a simple task + task.taskName = name; + task.displayName = name; + return task; +} +exports.define = define; diff --git a/build/lib/task.ts b/build/lib/task.ts new file mode 100644 index 00000000000..4e571ec9294 --- /dev/null +++ b/build/lib/task.ts @@ -0,0 +1,125 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as fancyLog from 'fancy-log'; +import * as ansiColors from 'ansi-colors'; + +export interface BaseTask { + displayName?: string; + taskName?: string; + _tasks?: Task[]; +} +export interface PromiseTask extends BaseTask { + (): Promise; +} +export interface StreamTask extends BaseTask { + (): NodeJS.ReadWriteStream; +} +export interface CallbackTask extends BaseTask { + (cb?: (err?: any) => void): void; +} + +export type Task = PromiseTask | StreamTask | CallbackTask; + +function _isPromise(p: Promise | NodeJS.ReadWriteStream): p is Promise { + if (typeof (p).then === 'function') { + return true; + } + return false; +} + +function _renderTime(time: number): string { + return `${Math.round(time)} ms`; +} + +async function _execute(task: Task): Promise { + const name = task.taskName || task.displayName || ``; + if (!task._tasks) { + fancyLog('Starting', ansiColors.cyan(name), '...'); + } + const startTime = process.hrtime(); + await _doExecute(task); + const elapsedArr = process.hrtime(startTime); + const elapsedNanoseconds = (elapsedArr[0] * 1e9 + elapsedArr[1]); + if (!task._tasks) { + fancyLog(`Finished`, ansiColors.cyan(name), 'after', ansiColors.magenta(_renderTime(elapsedNanoseconds / 1e6))); + } +} + +async function _doExecute(task: Task): Promise { + // Always invoke as if it were a callback task + return new Promise((resolve, reject) => { + if (task.length === 1) { + // this is a callback task + task((err) => { + if (err) { + return reject(err); + } + resolve(); + }); + return; + } + + const taskResult = task(); + + if (typeof taskResult === 'undefined') { + // this is a sync task + resolve(); + return; + } + + if (_isPromise(taskResult)) { + // this is a promise returning task + taskResult.then(resolve, reject); + return; + } + + // this is a stream returning task + taskResult.on('end', _ => resolve()); + taskResult.on('error', err => reject(err)); + }); +} + +export function series(...tasks: Task[]): PromiseTask { + const result = async () => { + for (let i = 0; i < tasks.length; i++) { + await _execute(tasks[i]); + } + }; + result._tasks = tasks; + return result; +} + +export function parallel(...tasks: Task[]): PromiseTask { + const result = async () => { + await Promise.all(tasks.map(t => _execute(t))); + }; + result._tasks = tasks; + return result; +} + +export function define(name: string, task: Task): Task { + if (task._tasks) { + // This is a composite task + const lastTask = task._tasks[task._tasks.length - 1]; + + if (lastTask._tasks || lastTask.taskName) { + // This is a composite task without a real task function + // => generate a fake task function + return define(name, series(task, () => Promise.resolve())); + } + + lastTask.taskName = name; + task.displayName = name; + return task; + } + + // This is a simple task + task.taskName = name; + task.displayName = name; + return task; +} diff --git a/build/lib/test/i18n.test.js b/build/lib/test/i18n.test.js index 8044a5eb711..3dd104259fa 100644 --- a/build/lib/test/i18n.test.js +++ b/build/lib/test/i18n.test.js @@ -27,14 +27,14 @@ suite('XLF Parser Tests', () => { }); test('JSON file source path to Transifex resource match', () => { const editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench'; - const platform = { name: 'vs/platform', project: editorProject }, editorContrib = { name: 'vs/editor/contrib', project: editorProject }, editor = { name: 'vs/editor', project: editorProject }, base = { name: 'vs/base', project: editorProject }, code = { name: 'vs/code', project: workbenchProject }, workbenchParts = { name: 'vs/workbench/parts/html', project: workbenchProject }, workbenchServices = { name: 'vs/workbench/services/files', project: workbenchProject }, workbench = { name: 'vs/workbench', project: workbenchProject }; + const platform = { name: 'vs/platform', project: editorProject }, editorContrib = { name: 'vs/editor/contrib', project: editorProject }, editor = { name: 'vs/editor', project: editorProject }, base = { name: 'vs/base', project: editorProject }, code = { name: 'vs/code', project: workbenchProject }, workbenchParts = { name: 'vs/workbench/contrib/html', project: workbenchProject }, workbenchServices = { name: 'vs/workbench/services/textfile', project: workbenchProject }, workbench = { name: 'vs/workbench', project: workbenchProject }; assert.deepEqual(i18n.getResource('vs/platform/actions/browser/menusExtensionPoint'), platform); assert.deepEqual(i18n.getResource('vs/editor/contrib/clipboard/browser/clipboard'), editorContrib); assert.deepEqual(i18n.getResource('vs/editor/common/modes/modesRegistry'), editor); assert.deepEqual(i18n.getResource('vs/base/common/errorMessage'), base); assert.deepEqual(i18n.getResource('vs/code/electron-main/window'), code); - assert.deepEqual(i18n.getResource('vs/workbench/parts/html/browser/webview'), workbenchParts); - assert.deepEqual(i18n.getResource('vs/workbench/services/files/node/fileService'), workbenchServices); + assert.deepEqual(i18n.getResource('vs/workbench/contrib/html/browser/webview'), workbenchParts); + assert.deepEqual(i18n.getResource('vs/workbench/services/textfile/node/testFileService'), workbenchServices); assert.deepEqual(i18n.getResource('vs/workbench/browser/parts/panel/panelActions'), workbench); }); }); diff --git a/build/lib/test/i18n.test.ts b/build/lib/test/i18n.test.ts index cfc1041974b..29a0f665799 100644 --- a/build/lib/test/i18n.test.ts +++ b/build/lib/test/i18n.test.ts @@ -38,8 +38,8 @@ suite('XLF Parser Tests', () => { editor = { name: 'vs/editor', project: editorProject }, base = { name: 'vs/base', project: editorProject }, code = { name: 'vs/code', project: workbenchProject }, - workbenchParts = { name: 'vs/workbench/parts/html', project: workbenchProject }, - workbenchServices = { name: 'vs/workbench/services/files', project: workbenchProject }, + workbenchParts = { name: 'vs/workbench/contrib/html', project: workbenchProject }, + workbenchServices = { name: 'vs/workbench/services/textfile', project: workbenchProject }, workbench = { name: 'vs/workbench', project: workbenchProject}; assert.deepEqual(i18n.getResource('vs/platform/actions/browser/menusExtensionPoint'), platform); @@ -47,8 +47,8 @@ suite('XLF Parser Tests', () => { assert.deepEqual(i18n.getResource('vs/editor/common/modes/modesRegistry'), editor); assert.deepEqual(i18n.getResource('vs/base/common/errorMessage'), base); assert.deepEqual(i18n.getResource('vs/code/electron-main/window'), code); - assert.deepEqual(i18n.getResource('vs/workbench/parts/html/browser/webview'), workbenchParts); - assert.deepEqual(i18n.getResource('vs/workbench/services/files/node/fileService'), workbenchServices); + assert.deepEqual(i18n.getResource('vs/workbench/contrib/html/browser/webview'), workbenchParts); + assert.deepEqual(i18n.getResource('vs/workbench/services/textfile/node/testFileService'), workbenchServices); assert.deepEqual(i18n.getResource('vs/workbench/browser/parts/panel/panelActions'), workbench); }); }); \ No newline at end of file diff --git a/build/lib/treeshaking.js b/build/lib/treeshaking.js index da51ac19104..50ff7caa01d 100644 --- a/build/lib/treeshaking.js +++ b/build/lib/treeshaking.js @@ -14,6 +14,17 @@ var ShakeLevel; ShakeLevel[ShakeLevel["InnerFile"] = 1] = "InnerFile"; ShakeLevel[ShakeLevel["ClassMembers"] = 2] = "ClassMembers"; })(ShakeLevel = exports.ShakeLevel || (exports.ShakeLevel = {})); +function toStringShakeLevel(shakeLevel) { + switch (shakeLevel) { + case 0 /* Files */: + return 'Files (0)'; + case 1 /* InnerFile */: + return 'InnerFile (1)'; + case 2 /* ClassMembers */: + return 'ClassMembers (2)'; + } +} +exports.toStringShakeLevel = toStringShakeLevel; function printDiagnostics(diagnostics) { for (const diag of diagnostics) { let result = ''; @@ -394,6 +405,7 @@ function markNodes(languageService, options) { || memberName === 'toJSON' || memberName === 'toString' || memberName === 'dispose' // TODO: keeping all `dispose` methods + || /^_(.*)Brand$/.test(memberName || '') // TODO: keeping all members ending with `Brand`... ) { enqueue_black(member); } @@ -513,10 +525,6 @@ function generateResult(languageService, shakeLevel) { // keep method continue; } - if (/^_(.*)Brand$/.test(member.name.getText())) { - // TODO: keep all members ending with `Brand`... - continue; - } let pos = member.pos - node.pos; let end = member.end - node.pos; toWrite = toWrite.substring(0, pos) + toWrite.substring(end); diff --git a/build/lib/treeshaking.ts b/build/lib/treeshaking.ts index 060808312e6..f0969633655 100644 --- a/build/lib/treeshaking.ts +++ b/build/lib/treeshaking.ts @@ -17,6 +17,17 @@ export const enum ShakeLevel { ClassMembers = 2 } +export function toStringShakeLevel(shakeLevel: ShakeLevel): string { + switch(shakeLevel) { + case ShakeLevel.Files: + return 'Files (0)'; + case ShakeLevel.InnerFile: + return 'InnerFile (1)'; + case ShakeLevel.ClassMembers: + return 'ClassMembers (2)'; + } +} + export interface ITreeShakingOptions { /** * The full path to the root where sources are. @@ -513,6 +524,7 @@ function markNodes(languageService: ts.LanguageService, options: ITreeShakingOpt || memberName === 'toJSON' || memberName === 'toString' || memberName === 'dispose'// TODO: keeping all `dispose` methods + || /^_(.*)Brand$/.test(memberName || '') // TODO: keeping all members ending with `Brand`... ) { enqueue_black(member); } @@ -642,10 +654,6 @@ function generateResult(languageService: ts.LanguageService, shakeLevel: ShakeLe // keep method continue; } - if (/^_(.*)Brand$/.test(member.name.getText())) { - // TODO: keep all members ending with `Brand`... - continue; - } let pos = member.pos - node.pos; let end = member.end - node.pos; diff --git a/build/lib/tslint/noNlsInStandaloneEditorRule.js b/build/lib/tslint/noNlsInStandaloneEditorRule.js new file mode 100644 index 00000000000..affd4cc8370 --- /dev/null +++ b/build/lib/tslint/noNlsInStandaloneEditorRule.js @@ -0,0 +1,54 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +const ts = require("typescript"); +const Lint = require("tslint"); +const path_1 = require("path"); +class Rule extends Lint.Rules.AbstractRule { + apply(sourceFile) { + if (/vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(sourceFile.fileName) + || /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(sourceFile.fileName) + || /vs(\/|\\)editor(\/|\\)editor.api/.test(sourceFile.fileName) + || /vs(\/|\\)editor(\/|\\)editor.main/.test(sourceFile.fileName) + || /vs(\/|\\)editor(\/|\\)editor.worker/.test(sourceFile.fileName)) { + return this.applyWithWalker(new NoNlsInStandaloneEditorRuleWalker(sourceFile, this.getOptions())); + } + return []; + } +} +exports.Rule = Rule; +class NoNlsInStandaloneEditorRuleWalker extends Lint.RuleWalker { + constructor(file, opts) { + super(file, opts); + } + visitImportEqualsDeclaration(node) { + if (node.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) { + this._validateImport(node.moduleReference.expression.getText(), node); + } + } + visitImportDeclaration(node) { + this._validateImport(node.moduleSpecifier.getText(), node); + } + visitCallExpression(node) { + super.visitCallExpression(node); + // import('foo') statements inside the code + if (node.expression.kind === ts.SyntaxKind.ImportKeyword) { + const [path] = node.arguments; + this._validateImport(path.getText(), node); + } + } + _validateImport(path, node) { + // remove quotes + path = path.slice(1, -1); + // resolve relative paths + if (path[0] === '.') { + path = path_1.join(this.getSourceFile().fileName, path); + } + if (/vs(\/|\\)nls/.test(path)) { + this.addFailure(this.createFailure(node.getStart(), node.getWidth(), `Not allowed to import vs/nls in standalone editor modules. Use standaloneStrings.ts`)); + } + } +} diff --git a/build/lib/tslint/noNlsInStandaloneEditorRule.ts b/build/lib/tslint/noNlsInStandaloneEditorRule.ts new file mode 100644 index 00000000000..ae23d74d784 --- /dev/null +++ b/build/lib/tslint/noNlsInStandaloneEditorRule.ts @@ -0,0 +1,67 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as ts from 'typescript'; +import * as Lint from 'tslint'; +import { join } from 'path'; + +export class Rule extends Lint.Rules.AbstractRule { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + if ( + /vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(sourceFile.fileName) + || /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(sourceFile.fileName) + || /vs(\/|\\)editor(\/|\\)editor.api/.test(sourceFile.fileName) + || /vs(\/|\\)editor(\/|\\)editor.main/.test(sourceFile.fileName) + || /vs(\/|\\)editor(\/|\\)editor.worker/.test(sourceFile.fileName) + ) { + return this.applyWithWalker(new NoNlsInStandaloneEditorRuleWalker(sourceFile, this.getOptions())); + } + + return []; + } +} + +class NoNlsInStandaloneEditorRuleWalker extends Lint.RuleWalker { + + constructor(file: ts.SourceFile, opts: Lint.IOptions) { + super(file, opts); + } + + protected visitImportEqualsDeclaration(node: ts.ImportEqualsDeclaration): void { + if (node.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) { + this._validateImport(node.moduleReference.expression.getText(), node); + } + } + + protected visitImportDeclaration(node: ts.ImportDeclaration): void { + this._validateImport(node.moduleSpecifier.getText(), node); + } + + protected visitCallExpression(node: ts.CallExpression): void { + super.visitCallExpression(node); + + // import('foo') statements inside the code + if (node.expression.kind === ts.SyntaxKind.ImportKeyword) { + const [path] = node.arguments; + this._validateImport(path.getText(), node); + } + } + + private _validateImport(path: string, node: ts.Node): void { + // remove quotes + path = path.slice(1, -1); + + // resolve relative paths + if (path[0] === '.') { + path = join(this.getSourceFile().fileName, path); + } + + if ( + /vs(\/|\\)nls/.test(path) + ) { + this.addFailure(this.createFailure(node.getStart(), node.getWidth(), `Not allowed to import vs/nls in standalone editor modules. Use standaloneStrings.ts`)); + } + } +} diff --git a/build/lib/tslint/noStandaloneEditorRule.js b/build/lib/tslint/noStandaloneEditorRule.js index 37bcf40e673..44b70a6a8d7 100644 --- a/build/lib/tslint/noStandaloneEditorRule.js +++ b/build/lib/tslint/noStandaloneEditorRule.js @@ -44,8 +44,8 @@ class NoStandaloneEditorRuleWalker extends Lint.RuleWalker { if (path[0] === '.') { path = path_1.join(this.getSourceFile().fileName, path); } - if (/vs(\/|\\)editor(\/|\\)standalone/.test(path) - || /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone/.test(path) + if (/vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(path) + || /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(path) || /vs(\/|\\)editor(\/|\\)editor.api/.test(path) || /vs(\/|\\)editor(\/|\\)editor.main/.test(path) || /vs(\/|\\)editor(\/|\\)editor.worker/.test(path)) { diff --git a/build/lib/tslint/noStandaloneEditorRule.ts b/build/lib/tslint/noStandaloneEditorRule.ts index b85e2da037a..713b94097d4 100644 --- a/build/lib/tslint/noStandaloneEditorRule.ts +++ b/build/lib/tslint/noStandaloneEditorRule.ts @@ -53,8 +53,8 @@ class NoStandaloneEditorRuleWalker extends Lint.RuleWalker { } if ( - /vs(\/|\\)editor(\/|\\)standalone/.test(path) - || /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone/.test(path) + /vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(path) + || /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(path) || /vs(\/|\\)editor(\/|\\)editor.api/.test(path) || /vs(\/|\\)editor(\/|\\)editor.main/.test(path) || /vs(\/|\\)editor(\/|\\)editor.worker/.test(path) diff --git a/build/lib/tslint/translationRemindRule.js b/build/lib/tslint/translationRemindRule.js index 45bbd4688f6..2234094421b 100644 --- a/build/lib/tslint/translationRemindRule.js +++ b/build/lib/tslint/translationRemindRule.js @@ -33,7 +33,7 @@ class TranslationRemindRuleWalker extends Lint.RuleWalker { visitImportLikeDeclaration(node) { const currentFile = node.getSourceFile().fileName; const matchService = currentFile.match(/vs\/workbench\/services\/\w+/); - const matchPart = currentFile.match(/vs\/workbench\/parts\/\w+/); + const matchPart = currentFile.match(/vs\/workbench\/contrib\/\w+/); if (!matchService && !matchPart) { return; } diff --git a/build/lib/tslint/translationRemindRule.ts b/build/lib/tslint/translationRemindRule.ts index 559b782c6da..e2671599d3c 100644 --- a/build/lib/tslint/translationRemindRule.ts +++ b/build/lib/tslint/translationRemindRule.ts @@ -42,7 +42,7 @@ class TranslationRemindRuleWalker extends Lint.RuleWalker { private visitImportLikeDeclaration(node: ts.ImportDeclaration | ts.ImportEqualsDeclaration) { const currentFile = node.getSourceFile().fileName; const matchService = currentFile.match(/vs\/workbench\/services\/\w+/); - const matchPart = currentFile.match(/vs\/workbench\/parts\/\w+/); + const matchPart = currentFile.match(/vs\/workbench\/contrib\/\w+/); if (!matchService && !matchPart) { return; } diff --git a/build/lib/typings/gulp-remote-src.d.ts b/build/lib/typings/gulp-remote-src.d.ts index 6ea57f84fe5..ff9026b79bb 100644 --- a/build/lib/typings/gulp-remote-src.d.ts +++ b/build/lib/typings/gulp-remote-src.d.ts @@ -1,4 +1,4 @@ -declare module 'gulp-remote-src' { +declare module 'gulp-remote-retry-src' { import stream = require("stream"); @@ -20,4 +20,4 @@ declare module 'gulp-remote-src' { } export = remote; -} \ No newline at end of file +} diff --git a/build/lib/util.js b/build/lib/util.js index e6f041f3d60..be2670261d7 100644 --- a/build/lib/util.js +++ b/build/lib/util.js @@ -8,7 +8,6 @@ const es = require("event-stream"); const debounce = require("debounce"); const _filter = require("gulp-filter"); const rename = require("gulp-rename"); -const _ = require("underscore"); const path = require("path"); const fs = require("fs"); const _rimraf = require("rimraf"); @@ -67,6 +66,9 @@ function fixWin32DirectoryPermissions() { exports.fixWin32DirectoryPermissions = fixWin32DirectoryPermissions; function setExecutableBit(pattern) { const setBit = es.mapSync(f => { + if (!f.stat) { + f.stat = { isFile() { return true; } }; + } f.stat.mode = /* 100755 */ 33261; return f; }); @@ -98,22 +100,18 @@ function skipDirectories() { }); } exports.skipDirectories = skipDirectories; -function cleanNodeModule(name, excludes, includes) { - const toGlob = (path) => '**/node_modules/' + name + (path ? '/' + path : ''); - const negate = (str) => '!' + str; - const allFilter = _filter(toGlob('**'), { restore: true }); - const globs = [toGlob('**')].concat(excludes.map(_.compose(negate, toGlob))); +function cleanNodeModules(rulePath) { + const rules = fs.readFileSync(rulePath, 'utf8') + .split(/\r?\n/g) + .map(line => line.trim()) + .filter(line => line && !/^#/.test(line)); + const excludes = rules.filter(line => !/^!/.test(line)).map(line => `!**/node_modules/${line}`); + const includes = rules.filter(line => /^!/.test(line)).map(line => `**/node_modules/${line.substr(1)}`); const input = es.through(); - const nodeModuleInput = input.pipe(allFilter); - let output = nodeModuleInput.pipe(_filter(globs)); - if (includes) { - const includeGlobs = includes.map(toGlob); - output = es.merge(output, nodeModuleInput.pipe(_filter(includeGlobs))); - } - output = output.pipe(allFilter.restore); + const output = es.merge(input.pipe(_filter(['**', ...excludes])), input.pipe(_filter(includes))); return es.duplex(input, output); } -exports.cleanNodeModule = cleanNodeModule; +exports.cleanNodeModules = cleanNodeModules; function loadSourcemaps() { const input = es.through(); const output = input @@ -180,7 +178,8 @@ function rimraf(dir) { return cb(err); }); }; - return cb => retry(cb); + retry.taskName = `clean-${path.basename(dir).toLowerCase()}`; + return retry; } exports.rimraf = rimraf; function getVersion(root) { diff --git a/build/lib/util.ts b/build/lib/util.ts index 4617cc83f2f..578271e6648 100644 --- a/build/lib/util.ts +++ b/build/lib/util.ts @@ -93,6 +93,9 @@ export function fixWin32DirectoryPermissions(): NodeJS.ReadWriteStream { export function setExecutableBit(pattern?: string | string[]): NodeJS.ReadWriteStream { const setBit = es.mapSync(f => { + if (!f.stat) { + f.stat = { isFile() { return true; } } as any; + } f.stat.mode = /* 100755 */ 33261; return f; }); @@ -129,23 +132,21 @@ export function skipDirectories(): NodeJS.ReadWriteStream { }); } -export function cleanNodeModule(name: string, excludes: string[], includes?: string[]): NodeJS.ReadWriteStream { - const toGlob = (path: string) => '**/node_modules/' + name + (path ? '/' + path : ''); - const negate = (str: string) => '!' + str; +export function cleanNodeModules(rulePath: string): NodeJS.ReadWriteStream { + const rules = fs.readFileSync(rulePath, 'utf8') + .split(/\r?\n/g) + .map(line => line.trim()) + .filter(line => line && !/^#/.test(line)); - const allFilter = _filter(toGlob('**'), { restore: true }); - const globs = [toGlob('**')].concat(excludes.map(_.compose(negate, toGlob) as (x: string) => string)); + const excludes = rules.filter(line => !/^!/.test(line)).map(line => `!**/node_modules/${line}`); + const includes = rules.filter(line => /^!/.test(line)).map(line => `**/node_modules/${line.substr(1)}`); const input = es.through(); - const nodeModuleInput = input.pipe(allFilter); - let output: NodeJS.ReadWriteStream = nodeModuleInput.pipe(_filter(globs)); + const output = es.merge( + input.pipe(_filter(['**', ...excludes])), + input.pipe(_filter(includes)) + ); - if (includes) { - const includeGlobs = includes.map(toGlob); - output = es.merge(output, nodeModuleInput.pipe(_filter(includeGlobs))); - } - - output = output.pipe(allFilter.restore); return es.duplex(input, output); } @@ -233,8 +234,8 @@ export function rimraf(dir: string): (cb: any) => void { return cb(err); }); }; - - return cb => retry(cb); + retry.taskName = `clean-${path.basename(dir).toLowerCase()}`; + return retry; } export function getVersion(root: string): string | undefined { diff --git a/build/lib/watch/package.json b/build/lib/watch/package.json index 0d031340153..b26f589ce0d 100644 --- a/build/lib/watch/package.json +++ b/build/lib/watch/package.json @@ -4,7 +4,8 @@ "description": "", "author": "Microsoft ", "private": true, + "license": "MIT", "devDependencies": { - "gulp-watch": "^4.3.9" + "gulp-watch": "5.0.1" } } diff --git a/build/lib/watch/yarn.lock b/build/lib/watch/yarn.lock index 0f2ac1e204d..f7d5d976b1f 100644 --- a/build/lib/watch/yarn.lock +++ b/build/lib/watch/yarn.lock @@ -7,23 +7,29 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -ajv@^4.9.1: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= +ansi-colors@1.1.0, ansi-colors@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" + integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA== dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" + ansi-wrap "^0.1.0" + +ansi-gray@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= + dependencies: + ansi-wrap "0.1.0" ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= +ansi-wrap@0.1.0, ansi-wrap@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= anymatch@^1.3.0: version "1.3.2" @@ -33,6 +39,14 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -53,97 +67,69 @@ arr-diff@^2.0.0: dependencies: arr-flatten "^1.0.1" -arr-flatten@^1.0.1: +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - -array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y= +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -assert-plus@1.0.0, assert-plus@^1.0.0: +assign-symbols@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - integrity sha1-104bh+ev/A24qttwIfP+SBAasjQ= +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== -async-each@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - integrity sha1-FDQt0428yU0OW4fXY81jYSwOeU8= - -aws4@^1.2.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - integrity sha1-g+9cqGCysy5KDe7e6MdxudtXRx4= +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - integrity sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40= +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: - tweetnacl "^0.14.3" - -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" binary-extensions@^1.0.0: version "1.10.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.10.0.tgz#9aeb9a6c5e88638aad171e167f5900abe24835d0" integrity sha1-muuabF6IY4qtFx4Wf1kAq+JINdA= -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - integrity sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8= - dependencies: - hoek "2.x.x" - brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" @@ -161,64 +147,127 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@^1.0.0, chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" -chokidar@^1.6.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: - anymatch "^1.3.0" - async-each "^1.0.0" - glob-parent "^2.0.0" - inherits "^2.0.1" + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +chokidar@^2.0.0: + version "2.1.6" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" + integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" is-binary-path "^1.0.0" - is-glob "^2.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" path-is-absolute "^1.0.0" - readdirp "^2.0.0" + readdirp "^2.2.1" + upath "^1.1.1" optionalDependencies: - fsevents "^1.0.0" + fsevents "^1.2.7" + +chownr@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" + integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +clone-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= clone-stats@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= +clone-stats@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= + clone@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" integrity sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8= -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= +clone@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +cloneable-readable@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec" + integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ== + dependencies: + inherits "^2.0.1" + process-nextick-args "^2.0.0" + readable-stream "^2.3.5" code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - integrity sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk= +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: - delayed-stream "~1.0.0" + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== concat-map@0.0.1: version "0.0.1" @@ -230,46 +279,61 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -core-util-is@1.0.2, core-util-is@~1.0.0: +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - integrity sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g= - dependencies: - boom "2.x.x" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= - -debug@^2.2.0: +debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -deep-extend@~0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" - integrity sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8= +debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" -delayed-stream@~1.0.0: +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" delegates@^1.0.0: version "1.0.0" @@ -281,25 +345,6 @@ detect-libc@^1.0.2: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.2.tgz#71ad5d204bf17a6a6ca8f450c61454066ef461e1" integrity sha1-ca1dIEvxempsqPRQxhRUBm70YeE= -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= - dependencies: - readable-stream "~1.1.9" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - integrity sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU= - dependencies: - jsbn "~0.1.0" - -escape-string-regexp@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -307,6 +352,19 @@ expand-brackets@^0.1.4: dependencies: is-posix-bracket "^0.1.0" +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" @@ -314,10 +372,20 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" -extend@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - integrity sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ= +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" extglob@^0.3.1: version "0.3.2" @@ -326,17 +394,27 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" -extsprintf@1.3.0, extsprintf@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -fancy-log@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948" - integrity sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg= +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: - chalk "^1.1.1" + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +fancy-log@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" + integrity sha1-9BEl49hPLn2JpD0G2VjI94vha+E= + dependencies: + ansi-gray "^0.1.1" + color-support "^1.1.3" time-stamp "^1.0.0" filename-regex@^2.0.0: @@ -355,6 +433,16 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + first-chunk-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz#1bdecdb8e083c0664b91945581577a43a9f31d70" @@ -362,7 +450,7 @@ first-chunk-stream@^2.0.0: dependencies: readable-stream "^2.0.2" -for-in@^1.0.1: +for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= @@ -374,51 +462,32 @@ for-own@^0.1.4: dependencies: for-in "^1.0.1" -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - integrity sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE= +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" + map-cache "^0.2.2" + +fs-minipass@^1.2.5: + version "1.2.6" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" + integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== + dependencies: + minipass "^2.2.1" fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" - integrity sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q== +fsevents@^1.2.7: + version "1.2.9" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" + integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== dependencies: - nan "^2.3.0" - node-pre-gyp "^0.6.39" - -fstream-ignore@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" - integrity sha1-nDHa40dnAY/h0kmyTa2mfQktoQU= - dependencies: - fstream "^1.0.0" - inherits "2" - minimatch "^3.0.0" - -fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" + nan "^2.12.1" + node-pre-gyp "^0.12.0" gauge@~2.7.3: version "2.7.4" @@ -434,12 +503,10 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= glob-base@^0.3.0: version "0.3.0" @@ -456,7 +523,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob-parent@^3.0.1: +glob-parent@^3.0.1, glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= @@ -476,120 +543,83 @@ glob@^7.0.5: once "^1.3.0" path-is-absolute "^1.0.0" -glogg@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" - integrity sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U= - dependencies: - sparkles "^1.0.0" +graceful-fs@^4.1.11: + version "4.2.0" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" + integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= -gulp-util@^3.0.7: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulp-watch@^4.3.9: - version "4.3.11" - resolved "https://registry.yarnpkg.com/gulp-watch/-/gulp-watch-4.3.11.tgz#162fc563de9fc770e91f9a7ce3955513a9a118c0" - integrity sha1-Fi/FY96fx3DpH5p845VVE6mhGMA= +gulp-watch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/gulp-watch/-/gulp-watch-5.0.1.tgz#83d378752f5bfb46da023e73c17ed1da7066215d" + integrity sha512-HnTSBdzAOFIT4wmXYPDUn783TaYAq9bpaN05vuZNP5eni3z3aRx0NAKbjhhMYtcq76x4R1wf4oORDGdlrEjuog== dependencies: + ansi-colors "1.1.0" anymatch "^1.3.0" - chokidar "^1.6.1" + chokidar "^2.0.0" + fancy-log "1.3.2" glob-parent "^3.0.1" - gulp-util "^3.0.7" object-assign "^4.1.0" path-is-absolute "^1.0.1" + plugin-error "1.0.1" readable-stream "^2.2.2" slash "^1.0.0" - vinyl "^1.2.0" + vinyl "^2.1.0" vinyl-file "^2.0.0" -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= - dependencies: - glogg "^1.0.0" - -har-schema@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" - integrity sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4= - -har-validator@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" - integrity sha1-M0gdDxu/9gDdID11gSpqX7oALio= - dependencies: - ajv "^4.9.1" - har-schema "^1.0.5" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= - dependencies: - sparkles "^1.0.0" - has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= -hawk@3.1.3, hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - integrity sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ= +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - integrity sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8= +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== + dependencies: + minimatch "^3.0.4" inflight@^1.0.4: version "1.0.6" @@ -599,16 +629,35 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" integrity sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4= +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -621,6 +670,38 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -633,17 +714,24 @@ is-equal-shallow@^0.1.3: dependencies: is-primitive "^2.0.0" -is-extendable@^0.1.1: +is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= -is-extglob@^2.1.0: +is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= @@ -669,6 +757,13 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" +is-glob@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -683,6 +778,13 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -693,20 +795,15 @@ is-primitive@^2.0.0: resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== isarray@1.0.0, isarray@~1.0.0: version "1.0.0" @@ -720,49 +817,12 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -kind-of@^3.0.2: +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= @@ -776,104 +836,27 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: - lodash._root "^3.0.0" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" + object-visit "^1.0.0" micromatch@^2.1.5: version "2.3.11" @@ -894,19 +877,26 @@ micromatch@^2.1.5: parse-glob "^3.0.4" regex-cache "^0.4.2" -mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" - integrity sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE= - -mime-types@^2.1.12, mime-types@~2.1.7: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" - integrity sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo= +micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: - mime-db "~1.30.0" + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -918,12 +908,35 @@ minimist@0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@^1.1.0, minimist@^1.2.0: +minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= -"mkdirp@>=0.5 0", mkdirp@^0.5.1: +minipass@^2.2.1, minipass@^2.3.5: + version "2.3.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" + integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" + integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== + dependencies: + minipass "^2.2.1" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -935,34 +948,57 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nan@^2.12.1: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: - duplexer2 "0.0.2" + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" -nan@^2.3.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46" - integrity sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY= +needle@^2.2.1: + version "2.4.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" + integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" -node-pre-gyp@^0.6.39: - version "0.6.39" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" - integrity sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ== +node-pre-gyp@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" + integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== dependencies: detect-libc "^1.0.2" - hawk "3.1.3" mkdirp "^0.5.1" + needle "^2.2.1" nopt "^4.0.1" + npm-packlist "^1.1.6" npmlog "^4.0.2" - rc "^1.1.7" - request "2.81.0" + rc "^1.2.7" rimraf "^2.6.1" semver "^5.3.0" - tar "^2.2.1" - tar-pack "^3.4.0" + tar "^4" nopt@^4.0.1: version "4.0.1" @@ -972,13 +1008,31 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-path@^2.0.0, normalize-path@^2.0.1: +normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-bundled@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" + integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + +npm-packlist@^1.1.6: + version "1.4.4" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" + integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -994,21 +1048,27 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= -oauth-sign@~0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= - object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -1017,7 +1077,14 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" -once@^1.3.0, once@^1.3.3: +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -1052,6 +1119,11 @@ parse-glob@^3.0.4: is-extglob "^1.0.0" is-glob "^2.0.0" +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -1062,11 +1134,6 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - integrity sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU= - pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -1084,26 +1151,36 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= +plugin-error@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c" + integrity sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA== + dependencies: + ansi-colors "^1.0.1" + arr-diff "^4.0.0" + arr-union "^3.1.0" + extend-shallow "^3.0.2" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= +process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -qs@~6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - integrity sha1-E+JtKK1rD/qpExLNO/cI7TUecjM= - randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" @@ -1112,17 +1189,17 @@ randomatic@^1.1.3: is-number "^3.0.0" kind-of "^4.0.0" -rc@^1.1.7: - version "1.2.2" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.2.tgz#d8ce9cb57e8d64d9c7badd9876c7c34cbe3c7077" - integrity sha1-2M6ctX6NZNnHut2YdsfDTL48cHc= +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: - deep-extend "~0.4.0" + deep-extend "^0.6.0" ini "~1.3.0" minimist "^1.2.0" strip-json-comments "~2.0.1" -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2: +readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" integrity sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ== @@ -1135,25 +1212,27 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable string_decoder "~1.0.3" util-deprecate "~1.0.1" -readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= +readable-stream@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== dependencies: core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" -readdirp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" - integrity sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg= +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: - graceful-fs "^4.1.2" - minimatch "^3.0.2" + graceful-fs "^4.1.11" + micromatch "^3.1.10" readable-stream "^2.0.2" - set-immediate-shim "^1.0.1" regex-cache@^0.4.2: version "0.4.4" @@ -1162,6 +1241,14 @@ regex-cache@^0.4.2: dependencies: is-equal-shallow "^0.1.3" +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -1172,7 +1259,7 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo= -repeat-string@^1.5.2: +repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -1182,46 +1269,55 @@ replace-ext@0.0.1: resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= -request@2.81.0: - version "2.81.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - integrity sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA= - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~4.2.1" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - performance-now "^0.2.0" - qs "~6.4.0" - safe-buffer "^5.0.1" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "^0.6.0" - uuid "^3.0.0" +replace-ext@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= -rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1: +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== dependencies: glob "^7.0.5" -safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.1.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + semver@^5.3.0: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -1232,10 +1328,15 @@ set-blocking@~2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" signal-exit@^3.0.0: version "3.0.2" @@ -1247,32 +1348,71 @@ slash@^1.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - integrity sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg= +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: - hoek "2.x.x" + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" -sparkles@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" - integrity sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM= - -sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" - integrity sha1-US322mKHFEMW3EwY/hzx2UBzm+M= +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" @@ -1283,11 +1423,6 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - string_decoder@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" @@ -1295,10 +1430,12 @@ string_decoder@~1.0.3: dependencies: safe-buffer "~5.1.0" -stringstream@~0.0.4: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - integrity sha1-TkhM1N5aC7vuGORjB3EKioFiGHg= +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" @@ -1327,90 +1464,87 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -tar-pack@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" - integrity sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg== +tar@^4: + version "4.4.10" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" + integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== dependencies: - debug "^2.2.0" - fstream "^1.0.10" - fstream-ignore "^1.0.5" - once "^1.3.3" - readable-stream "^2.1.4" - rimraf "^2.5.1" - tar "^2.2.1" - uid-number "^0.0.6" - -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -through2@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.3.5" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" time-stamp@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= -tough-cookie@~2.3.0: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" - integrity sha1-C2GKVWW23qkL80JdBNVe3EdadWE= +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: - punycode "^1.4.1" + kind-of "^3.0.2" -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: - safe-buffer "^5.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" -uid-number@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" - integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE= +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" + integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -uuid@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" - integrity sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g== - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - vinyl-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/vinyl-file/-/vinyl-file-2.0.0.tgz#a7ebf5ffbefda1b7d18d140fcb07b223efb6751a" @@ -1423,16 +1557,7 @@ vinyl-file@^2.0.0: strip-bom-stream "^2.0.0" vinyl "^1.1.0" -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^1.1.0, vinyl@^1.2.0: +vinyl@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= @@ -1441,6 +1566,18 @@ vinyl@^1.1.0, vinyl@^1.2.0: clone-stats "^0.0.1" replace-ext "0.0.1" +vinyl@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" + integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== + dependencies: + clone "^2.1.1" + clone-buffer "^1.0.0" + clone-stats "^1.0.0" + cloneable-readable "^1.0.0" + remove-trailing-separator "^1.0.1" + replace-ext "^1.0.0" + wide-align@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" @@ -1453,7 +1590,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= +yallist@^3.0.0, yallist@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" + integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== diff --git a/build/monaco/ThirdPartyNotices.txt b/build/monaco/ThirdPartyNotices.txt index a459893cc97..1de70ddaab6 100644 --- a/build/monaco/ThirdPartyNotices.txt +++ b/build/monaco/ThirdPartyNotices.txt @@ -7,6 +7,31 @@ herein, whether by implication, estoppel or otherwise. +%% nodejs path library (https://github.com/nodejs/node/tree/43dd49c9782848c25e5b03448c8a0f923f13c158) +========================================= +Copyright Joyent, Inc. and other Node contributors. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= +END OF nodejs path library NOTICES AND INFORMATION + %% promise-polyfill version 8.1.0 (https://github.com/taylorhakes/promise-polyfill) ========================================= diff --git a/build/monaco/api.js b/build/monaco/api.js index 716d1f56655..5cd0be82039 100644 --- a/build/monaco/api.js +++ b/build/monaco/api.js @@ -7,14 +7,15 @@ Object.defineProperty(exports, "__esModule", { value: true }); const fs = require("fs"); const ts = require("typescript"); const path = require("path"); -const util = require("gulp-util"); +const fancyLog = require("fancy-log"); +const ansiColors = require("ansi-colors"); const dtsv = '2'; const tsfmt = require('../../tsfmt.json'); const SRC = path.join(__dirname, '../../src'); exports.RECIPE_PATH = path.join(__dirname, './monaco.d.ts.recipe'); const DECLARATION_PATH = path.join(__dirname, '../../src/vs/monaco.d.ts'); function logErr(message, ...rest) { - util.log(util.colors.yellow(`[monaco.d.ts]`), message, ...rest); + fancyLog(ansiColors.yellow(`[monaco.d.ts]`), message, ...rest); } function isDeclaration(a) { return (a.kind === ts.SyntaxKind.InterfaceDeclaration @@ -305,8 +306,8 @@ function generateDeclarationFile(recipe, sourceFileGetter) { let usageImports = []; let usage = []; let failed = false; - usage.push(`var a;`); - usage.push(`var b;`); + usage.push(`var a: any;`); + usage.push(`var b: any;`); const generateUsageImport = (moduleId) => { let importName = 'm' + (++usageCounter); usageImports.push(`import * as ${importName} from './${moduleId.replace(/\.d\.ts$/, '')}';`); @@ -456,11 +457,20 @@ class FSProvider { existsSync(filePath) { return fs.existsSync(filePath); } + statSync(filePath) { + return fs.statSync(filePath); + } readFileSync(_moduleId, filePath) { return fs.readFileSync(filePath); } } exports.FSProvider = FSProvider; +class CacheEntry { + constructor(sourceFile, mtime) { + this.sourceFile = sourceFile; + this.mtime = mtime; + } +} class DeclarationResolver { constructor(_fsProvider) { this._fsProvider = _fsProvider; @@ -470,31 +480,43 @@ class DeclarationResolver { this._sourceFileCache[moduleId] = null; } getDeclarationSourceFile(moduleId) { + if (this._sourceFileCache[moduleId]) { + // Since we cannot trust file watching to invalidate the cache, check also the mtime + const fileName = this._getFileName(moduleId); + const mtime = this._fsProvider.statSync(fileName).mtime.getTime(); + if (this._sourceFileCache[moduleId].mtime !== mtime) { + this._sourceFileCache[moduleId] = null; + } + } if (!this._sourceFileCache[moduleId]) { this._sourceFileCache[moduleId] = this._getDeclarationSourceFile(moduleId); } - return this._sourceFileCache[moduleId]; + return this._sourceFileCache[moduleId] ? this._sourceFileCache[moduleId].sourceFile : null; + } + _getFileName(moduleId) { + if (/\.d\.ts$/.test(moduleId)) { + return path.join(SRC, moduleId); + } + return path.join(SRC, `${moduleId}.ts`); } _getDeclarationSourceFile(moduleId) { - if (/\.d\.ts$/.test(moduleId)) { - const fileName = path.join(SRC, moduleId); - if (!this._fsProvider.existsSync(fileName)) { - return null; - } - const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString(); - return ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5); - } - const fileName = path.join(SRC, `${moduleId}.ts`); + const fileName = this._getFileName(moduleId); if (!this._fsProvider.existsSync(fileName)) { return null; } + const mtime = this._fsProvider.statSync(fileName).mtime.getTime(); + if (/\.d\.ts$/.test(moduleId)) { + // const mtime = this._fsProvider.statFileSync() + const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString(); + return new CacheEntry(ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5), mtime); + } const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString(); const fileMap = { 'file.ts': fileContents }; const service = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, fileMap, {})); const text = service.getEmitOutput('file.ts', true).outputFiles[0].text; - return ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5); + return new CacheEntry(ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5), mtime); } } exports.DeclarationResolver = DeclarationResolver; diff --git a/build/monaco/api.ts b/build/monaco/api.ts index d12b77787a0..ef9c9a584dc 100644 --- a/build/monaco/api.ts +++ b/build/monaco/api.ts @@ -6,7 +6,8 @@ import * as fs from 'fs'; import * as ts from 'typescript'; import * as path from 'path'; -import * as util from 'gulp-util'; +import * as fancyLog from 'fancy-log'; +import * as ansiColors from 'ansi-colors'; const dtsv = '2'; @@ -17,7 +18,7 @@ export const RECIPE_PATH = path.join(__dirname, './monaco.d.ts.recipe'); const DECLARATION_PATH = path.join(__dirname, '../../src/vs/monaco.d.ts'); function logErr(message: any, ...rest: any[]): void { - util.log(util.colors.yellow(`[monaco.d.ts]`), message, ...rest); + fancyLog(ansiColors.yellow(`[monaco.d.ts]`), message, ...rest); } type SourceFileGetter = (moduleId: string) => ts.SourceFile | null; @@ -365,8 +366,8 @@ function generateDeclarationFile(recipe: string, sourceFileGetter: SourceFileGet let failed = false; - usage.push(`var a;`); - usage.push(`var b;`); + usage.push(`var a: any;`); + usage.push(`var b: any;`); const generateUsageImport = (moduleId: string) => { let importName = 'm' + (++usageCounter); @@ -547,14 +548,24 @@ export class FSProvider { public existsSync(filePath: string): boolean { return fs.existsSync(filePath); } + public statSync(filePath: string): fs.Stats { + return fs.statSync(filePath); + } public readFileSync(_moduleId: string, filePath: string): Buffer { return fs.readFileSync(filePath); } } +class CacheEntry { + constructor( + public readonly sourceFile: ts.SourceFile, + public readonly mtime: number + ) {} +} + export class DeclarationResolver { - private _sourceFileCache: { [moduleId: string]: ts.SourceFile | null; }; + private _sourceFileCache: { [moduleId: string]: CacheEntry | null; }; constructor(private readonly _fsProvider: FSProvider) { this._sourceFileCache = Object.create(null); @@ -565,32 +576,51 @@ export class DeclarationResolver { } public getDeclarationSourceFile(moduleId: string): ts.SourceFile | null { + if (this._sourceFileCache[moduleId]) { + // Since we cannot trust file watching to invalidate the cache, check also the mtime + const fileName = this._getFileName(moduleId); + const mtime = this._fsProvider.statSync(fileName).mtime.getTime(); + if (this._sourceFileCache[moduleId]!.mtime !== mtime) { + this._sourceFileCache[moduleId] = null; + } + } if (!this._sourceFileCache[moduleId]) { this._sourceFileCache[moduleId] = this._getDeclarationSourceFile(moduleId); } - return this._sourceFileCache[moduleId]; + return this._sourceFileCache[moduleId] ? this._sourceFileCache[moduleId]!.sourceFile : null; } - private _getDeclarationSourceFile(moduleId: string): ts.SourceFile | null { + private _getFileName(moduleId: string): string { if (/\.d\.ts$/.test(moduleId)) { - const fileName = path.join(SRC, moduleId); - if (!this._fsProvider.existsSync(fileName)) { - return null; - } - const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString(); - return ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5); + return path.join(SRC, moduleId); } - const fileName = path.join(SRC, `${moduleId}.ts`); + return path.join(SRC, `${moduleId}.ts`); + } + + private _getDeclarationSourceFile(moduleId: string): CacheEntry | null { + const fileName = this._getFileName(moduleId); if (!this._fsProvider.existsSync(fileName)) { return null; } + const mtime = this._fsProvider.statSync(fileName).mtime.getTime(); + if (/\.d\.ts$/.test(moduleId)) { + // const mtime = this._fsProvider.statFileSync() + const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString(); + return new CacheEntry( + ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5), + mtime + ); + } const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString(); const fileMap: IFileMap = { 'file.ts': fileContents }; const service = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, fileMap, {})); const text = service.getEmitOutput('file.ts', true).outputFiles[0].text; - return ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5); + return new CacheEntry( + ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5), + mtime + ); } } diff --git a/build/monaco/monaco.d.ts.recipe b/build/monaco/monaco.d.ts.recipe index ed3a8f5d260..afba093b25c 100644 --- a/build/monaco/monaco.d.ts.recipe +++ b/build/monaco/monaco.d.ts.recipe @@ -5,6 +5,8 @@ declare namespace monaco { + // THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY. + export type Thenable = PromiseLike; export interface IDisposable { diff --git a/build/monaco/monaco.usage.recipe b/build/monaco/monaco.usage.recipe index e75b8585a2d..f1a74a25e30 100644 --- a/build/monaco/monaco.usage.recipe +++ b/build/monaco/monaco.usage.recipe @@ -10,8 +10,10 @@ import { CountBadge } from './vs/base/browser/ui/countBadge/countBadge'; import { SimpleWorkerClient, create as create1 } from './vs/base/common/worker/simpleWorker'; import { create as create2 } from './vs/editor/common/services/editorSimpleWorker'; import { QuickOpenWidget } from './vs/base/parts/quickopen/browser/quickOpenWidget'; +import { WorkbenchAsyncDataTree } from './vs/platform/list/browser/listService'; import { SyncDescriptor0, SyncDescriptor1, SyncDescriptor2, SyncDescriptor3, SyncDescriptor4, SyncDescriptor5, SyncDescriptor6, SyncDescriptor7, SyncDescriptor8 } from './vs/platform/instantiation/common/descriptors'; import { DiffNavigator } from './vs/editor/browser/widget/diffNavigator'; +import { DocumentRangeFormattingEditProvider } from './vs/editor/common/modes'; import * as editorAPI from './vs/editor/editor.api'; (function () { @@ -22,14 +24,16 @@ import * as editorAPI from './vs/editor/editor.api'; a = (b).getWorkspace; // IWorkspaceFolderProvider a = (b).style; // IThemable a = (b).style; // IThemable + a = (>b).style; // IThemable a = (b).userHome; // IUserHomeProvider a = (b).previous; // IDiffNavigator a = (>b).type; a = (b).start; a = (b).end; - a = (>b).getProxyObject; // IWorkerClient + a = (>b).getProxyObject; // IWorkerClient a = create1; a = create2; + a = (b).extensionId; // injection madness a = (>b).ctor; diff --git a/build/monaco/package.json b/build/monaco/package.json index efd919085b2..1962694ce6d 100644 --- a/build/monaco/package.json +++ b/build/monaco/package.json @@ -1,7 +1,7 @@ { "name": "monaco-editor-core", "private": true, - "version": "0.14.3", + "version": "0.16.0", "description": "A browser based code editor", "author": "Microsoft Corporation", "license": "MIT", diff --git a/src/vs/base/test/node/stream/fixtures/empty.txt b/build/monaco/version.txt similarity index 100% rename from src/vs/base/test/node/stream/fixtures/empty.txt rename to build/monaco/version.txt diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index ea2d2d9a2dc..cd41092192c 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -17,7 +17,14 @@ function yarnInstall(location, opts) { opts.cwd = location; opts.stdio = 'inherit'; - const result = cp.spawnSync(yarn, ['install'], opts); + const raw = process.env['npm_config_argv'] || '{}'; + const argv = JSON.parse(raw); + const original = argv.original || []; + const args = original.filter(arg => arg === '--ignore-optional' || arg === '--frozen-lockfile'); + + console.log(`Installing dependencies in ${location}...`); + console.log(`$ yarn ${args.join(' ')}`); + const result = cp.spawnSync(yarn, args, opts); if (result.error || result.status !== 0) { process.exit(1); @@ -26,6 +33,10 @@ function yarnInstall(location, opts) { yarnInstall('extensions'); // node modules shared by all extensions +yarnInstall('remote'); // node modules used by vscode server + +yarnInstall('remote/web'); // node modules used by vscode web + const allExtensionFolders = fs.readdirSync('extensions'); const extensions = allExtensionFolders.filter(e => { try { diff --git a/build/npm/preinstall.js b/build/npm/preinstall.js index a2029c364fa..3b0d7dc538f 100644 --- a/build/npm/preinstall.js +++ b/build/npm/preinstall.js @@ -7,8 +7,8 @@ let err = false; const majorNodeVersion = parseInt(/^(\d+)\./.exec(process.versions.node)[1]); -if (majorNodeVersion < 8 || majorNodeVersion >= 9) { - console.error('\033[1;31m*** Please use node >=8 and <9.\033[0;0m'); +if (majorNodeVersion < 8 || majorNodeVersion >= 11) { + console.error('\033[1;31m*** Please use node >=8 and <11.\033[0;0m'); err = true; } diff --git a/build/npm/update-distro.js b/build/npm/update-distro.js new file mode 100644 index 00000000000..947a4967d60 --- /dev/null +++ b/build/npm/update-distro.js @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const cp = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const rootPath = path.dirname(path.dirname(path.dirname(__dirname))); +const vscodePath = path.join(rootPath, 'vscode'); +const distroPath = path.join(rootPath, 'vscode-distro'); +const commit = cp.execSync('git rev-parse HEAD', { cwd: distroPath, encoding: 'utf8' }).trim(); +const packageJsonPath = path.join(vscodePath, 'package.json'); +const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); + +packageJson.distro = commit; +fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); \ No newline at end of file diff --git a/build/npm/update-grammar.js b/build/npm/update-grammar.js index b4f94044419..5321b7b1dcd 100644 --- a/build/npm/update-grammar.js +++ b/build/npm/update-grammar.js @@ -12,6 +12,8 @@ var cson = require('cson-parser'); var https = require('https'); var url = require('url'); +let commitDate = '0000-00-00'; + /** * @param {string} urlString */ @@ -80,7 +82,7 @@ function getCommitSha(repoId, repoPath) { }); } -exports.update = function (repoId, repoPath, dest, modifyGrammar, version = 'master') { +exports.update = function (repoId, repoPath, dest, modifyGrammar, version = 'master', packageJsonPathOverride = '') { var contentPath = 'https://raw.githubusercontent.com/' + repoId + `/${version}/` + repoPath; console.log('Reading from ' + contentPath); return download(contentPath).then(function (content) { @@ -120,30 +122,39 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar, version = 'mas try { fs.writeFileSync(dest, JSON.stringify(result, null, '\t').replace(/\n/g, '\r\n')); - // Add commit sha to cgmanifest let cgmanifestRead = JSON.parse(fs.readFileSync('./cgmanifest.json').toString()); let promises = new Array(); - let packageJsonPath = 'https://raw.githubusercontent.com/' + repoId + `/${info.commitSha}/package.json`; - for (let i = 0; i < cgmanifestRead.registrations.length; i++) { - if (cgmanifestRead.registrations[i].component.git.repositoryUrl.substr(cgmanifestRead.registrations[i].component.git.repositoryUrl.length - repoId.length, repoId.length) === repoId) { - cgmanifestRead.registrations[i].component.git.commitHash = info.commitSha; - promises.push(download(packageJsonPath).then(function (packageJson) { - if (packageJson) { - try { - cgmanifestRead.registrations[i].version = JSON.parse(packageJson).version; - } catch (e) { - console.log('File does not exist at' + packageJsonPath); - } - } - })); - break; + const currentCommitDate = info.commitDate.substr(0, 10); + + // Add commit sha to cgmanifest. + if (currentCommitDate > commitDate) { + let packageJsonPath = 'https://raw.githubusercontent.com/' + repoId + `/${info.commitSha}/`; + if (packageJsonPathOverride) { + packageJsonPath += packageJsonPathOverride; + } + packageJsonPath += '/package.json'; + for (let i = 0; i < cgmanifestRead.registrations.length; i++) { + if (cgmanifestRead.registrations[i].component.git.repositoryUrl.substr(cgmanifestRead.registrations[i].component.git.repositoryUrl.length - repoId.length, repoId.length) === repoId) { + cgmanifestRead.registrations[i].component.git.commitHash = info.commitSha; + commitDate = currentCommitDate; + promises.push(download(packageJsonPath).then(function (packageJson) { + if (packageJson) { + try { + cgmanifestRead.registrations[i].version = JSON.parse(packageJson).version; + } catch (e) { + console.log('Cannot get version. File does not exist at ' + packageJsonPath); + } + } + })); + break; + } } } Promise.all(promises).then(function (allResult) { fs.writeFileSync('./cgmanifest.json', JSON.stringify(cgmanifestRead, null, '\t').replace(/\n/g, '\r\n')); }); if (info) { - console.log('Updated ' + path.basename(dest) + ' to ' + repoId + '@' + info.commitSha.substr(0, 7) + ' (' + info.commitDate.substr(0, 10) + ')'); + console.log('Updated ' + path.basename(dest) + ' to ' + repoId + '@' + info.commitSha.substr(0, 7) + ' (' + currentCommitDate + ')'); } else { console.log('Updated ' + path.basename(dest)); } diff --git a/build/npm/update-localization-extension.js b/build/npm/update-localization-extension.js index 50dcaca3eb6..b1656dc88f4 100644 --- a/build/npm/update-localization-extension.js +++ b/build/npm/update-localization-extension.js @@ -74,7 +74,7 @@ function update(options) { let translationPaths = []; i18n.pullI18nPackFiles(server, userName, apiToken, { id: languageId }, translationPaths) .on('error', (error) => { - console.log(`Error occured while importing translations:`); + console.log(`Error occurred while importing translations:`); translationPaths = undefined; if (Array.isArray(error)) { error.forEach(console.log); @@ -100,7 +100,7 @@ function update(options) { gulp.src(path.join(location, languageId, '**', '*.xlf')) .pipe(i18n.prepareI18nPackFiles(i18n.externalExtensionsWithTranslations, translationPaths, languageId === 'ps')) .on('error', (error) => { - console.log(`Error occured while importing translations:`); + console.log(`Error occurred while importing translations:`); translationPaths = undefined; if (Array.isArray(error)) { error.forEach(console.log); diff --git a/build/package.json b/build/package.json index 64c0f9277b0..a382150c3f0 100644 --- a/build/package.json +++ b/build/package.json @@ -1,10 +1,13 @@ { "name": "code-oss-dev-build", "version": "1.0.0", + "license": "MIT", "devDependencies": { + "@types/ansi-colors": "^3.2.0", "@types/azure": "0.9.19", "@types/debounce": "^1.0.0", "@types/documentdb": "1.10.2", + "@types/fancy-log": "^1.3.0", "@types/glob": "^7.1.1", "@types/gulp": "^4.0.5", "@types/gulp-concat": "^0.0.32", @@ -13,12 +16,11 @@ "@types/gulp-rename": "^0.0.33", "@types/gulp-sourcemaps": "^0.0.32", "@types/gulp-uglify": "^3.0.5", - "@types/gulp-util": "^3.0.34", "@types/mime": "0.0.29", "@types/minimatch": "^3.0.3", "@types/minimist": "^1.2.0", "@types/mocha": "2.2.39", - "@types/node": "8.0.33", + "@types/node": "^10.14.8", "@types/pump": "^1.0.1", "@types/request": "^2.47.0", "@types/rimraf": "^2.0.2", @@ -27,7 +29,7 @@ "@types/uglify-es": "^3.0.0", "@types/underscore": "^1.8.9", "@types/xml2js": "0.0.33", - "applicationinsights": "1.0.6", + "applicationinsights": "1.0.8", "azure-storage": "^2.1.0", "documentdb": "1.13.0", "github-releases": "^0.4.1", @@ -38,8 +40,9 @@ "minimist": "^1.2.0", "request": "^2.85.0", "tslint": "^5.9.1", - "typescript": "3.2.2", + "typescript": "3.5.2", "vsce": "1.48.0", + "vscode-telemetry-extractor": "1.5.3", "xml2js": "^0.4.17" }, "scripts": { diff --git a/build/tsconfig.json b/build/tsconfig.json index 46ad745bc23..df15ccdd1be 100644 --- a/build/tsconfig.json +++ b/build/tsconfig.json @@ -8,7 +8,7 @@ "resolveJsonModule": true, "experimentalDecorators": true, // enable JavaScript type checking for the language service - // use the tsconfig.build.json for compiling wich disable JavaScript + // use the tsconfig.build.json for compiling which disable JavaScript // type checking so that JavaScript file are not transpiled "allowJs": true, "checkJs": true, @@ -22,4 +22,4 @@ "exclude": [ "node_modules/**" ] -} \ No newline at end of file +} diff --git a/build/win32/Cargo.lock b/build/win32/Cargo.lock index dcc1440b35e..3c95fb34cdf 100644 --- a/build/win32/Cargo.lock +++ b/build/win32/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "build_const" version = "0.2.0" @@ -27,7 +29,7 @@ dependencies = [ [[package]] name = "inno_updater" -version = "0.7.1" +version = "0.8.0" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/build/win32/code.iss b/build/win32/code.iss index 43572199eb5..831b31a3c71 100644 --- a/build/win32/code.iss +++ b/build/win32/code.iss @@ -1,7 +1,7 @@ #define LocalizedLanguageFile(Language = "") \ DirExists(RepoDir + "\licenses") && Language != "" \ - ? ('; LicenseFile: "' + RepoDir + '\licenses\LICENSE-' + Language + '.txt"') \ - : '; LicenseFile: "' + RepoDir + '\LICENSE.txt"' + ? ('; LicenseFile: "' + RepoDir + '\licenses\LICENSE-' + Language + '.rtf"') \ + : '; LicenseFile: "' + RepoDir + '\LICENSE.rtf"' [Setup] AppId={#AppId} @@ -1034,7 +1034,7 @@ begin AltArch := '32'; end; - if not Result then begin + if not Result and not WizardSilent() then begin MsgBox('Please uninstall the ' + AltArch + '-bit version of {#NameShort} before installing this ' + ThisArch + '-bit version.', mbInformation, MB_OK); end; end; diff --git a/build/win32/i18n/messages.en.isl b/build/win32/i18n/messages.en.isl index 4bd6c75ad43..a6aab59b95a 100644 --- a/build/win32/i18n/messages.en.isl +++ b/build/win32/i18n/messages.en.isl @@ -2,7 +2,7 @@ AddContextMenuFiles=Add "Open with %1" action to Windows Explorer file context menu AddContextMenuFolders=Add "Open with %1" action to Windows Explorer directory context menu AssociateWithFiles=Register %1 as an editor for supported file types -AddToPath=Add to PATH (available after restart) +AddToPath=Add to PATH (requires shell restart) RunAfter=Run %1 after installation Other=Other: SourceFile=%1 Source File \ No newline at end of file diff --git a/build/win32/inno_updater.exe b/build/win32/inno_updater.exe index 140065f673c..baca28361d1 100644 Binary files a/build/win32/inno_updater.exe and b/build/win32/inno_updater.exe differ diff --git a/build/yarn.lock b/build/yarn.lock index 4d2a53c8ee7..23ac4d9b84d 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -2,6 +2,14 @@ # yarn lockfile v1 +"@dsherret/to-absolute-glob@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@dsherret/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1f6475dc8bd974cea07a2daf3864b317b1dd332c" + integrity sha1-H2R13IvZdM6gei2vOGSzF7HdMyw= + dependencies: + is-absolute "^1.0.0" + is-negated-glob "^1.0.0" + "@gulp-sourcemaps/map-sources@1.X": version "1.0.0" resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda" @@ -10,6 +18,32 @@ normalize-path "^2.0.1" through2 "^2.0.3" +"@nodelib/fs.scandir@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz#7fa8fed654939e1a39753d286b48b4836d00e0eb" + integrity sha512-NT/skIZjgotDSiXs0WqYhgcuBKhUMgfekCmCGtkUAiLqZdOnrdjmZr9wRl3ll64J9NF79uZ4fk16Dx0yMc/Xbg== + dependencies: + "@nodelib/fs.stat" "2.0.1" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.1", "@nodelib/fs.stat@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.1.tgz#814f71b1167390cfcb6a6b3d9cdeb0951a192c14" + integrity sha512-+RqhBlLn6YRBGOIoVYthsG0J9dfpO79eJyN7BYBkZJtfqrBwf2KK+rD/M/yjZR6WBmIhAgOV7S60eCgaSWtbFw== + +"@nodelib/fs.walk@^1.2.1": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.2.tgz#6a6450c5e17012abd81450eb74949a4d970d2807" + integrity sha512-J/DR3+W12uCzAJkw7niXDcqcKBg6+5G5Q/ZpThpGNzAUz70eOR6RV4XnnSN01qHZiVl0eavoxJsBypQoKsV2QQ== + dependencies: + "@nodelib/fs.scandir" "2.1.1" + fastq "^1.6.0" + +"@types/ansi-colors@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@types/ansi-colors/-/ansi-colors-3.2.0.tgz#3e4fe85d9131ce1c6994f3040bd0b25306c16a6e" + integrity sha512-0caWAhXht9N2lOdMzJLXybsSkYCx1QOdxx6pae48tswI9QV3DFX26AoOpy0JxwhCb+zISTqmd6H8t9Zby9BoZg== + "@types/azure@0.9.19": version "0.9.19" resolved "https://registry.yarnpkg.com/@types/azure/-/azure-0.9.19.tgz#1a6a9bd856b437ddecf3f9fc8407a683c869ba02" @@ -47,6 +81,11 @@ resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" integrity sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA== +"@types/fancy-log@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@types/fancy-log/-/fancy-log-1.3.0.tgz#a61ab476e5e628cd07a846330df53b85e05c8ce0" + integrity sha512-mQjDxyOM1Cpocd+vm1kZBP7smwKZ4TNokFeds9LV7OZibmPJFEzY3+xZMrKfUdNT71lv8GoCPD6upKwHxubClw== + "@types/form-data@*": version "2.2.1" resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-2.2.1.tgz#ee2b3b8eaa11c0938289953606b745b738c54b1e" @@ -117,16 +156,6 @@ "@types/node" "*" "@types/uglify-js" "^2" -"@types/gulp-util@^3.0.34": - version "3.0.34" - resolved "https://registry.yarnpkg.com/@types/gulp-util/-/gulp-util-3.0.34.tgz#d1291ebf706d93f46eb8df11344bbfd96247697e" - integrity sha512-E06WN1OfqL5UsMwJ1T7ClgnaXgaPipb7Ee8euMc3KRHLNqxdvWrDir9KA6uevgzBgT7XbjgmzZA2pkzDqBBX7A== - dependencies: - "@types/node" "*" - "@types/through2" "*" - "@types/vinyl" "*" - chalk "^2.2.0" - "@types/gulp@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@types/gulp/-/gulp-4.0.5.tgz#f5f498d5bf9538364792de22490a12c0e6bc5eb4" @@ -166,10 +195,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb" integrity sha512-El3+WJk2D/ppWNd2X05aiP5l2k4EwF7KwheknQZls+I26eSICoWRhRIJ56jGgw2dqNGQ5LtNajmBU2ajS28EvQ== -"@types/node@8.0.33": - version "8.0.33" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd" - integrity sha512-vmCdO8Bm1ExT+FWfC9sd9r4jwqM7o97gGy2WBshkkXbf/2nLAJQUrZfIhw27yVOtLUev6kSZc4cav/46KbDd8A== +"@types/node@^10.14.8": + version "10.14.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.13.tgz#ac786d623860adf39a3f51d629480aacd6a6eec7" + integrity sha512-yN/FNNW1UYsRR1wwAoyOwqvDuLDtVXnaJTZ898XIw/Q5cCaeVAlVwvsmXLX5PuiScBYwZsZU4JYSHB3TvfdwvQ== "@types/pump@^1.0.1": version "1.0.1" @@ -196,7 +225,7 @@ "@types/glob" "*" "@types/node" "*" -"@types/through2@*", "@types/through2@^2.0.34": +"@types/through2@^2.0.34": version "2.0.34" resolved "https://registry.yarnpkg.com/@types/through2/-/through2-2.0.34.tgz#9c2a259a238dace2a05a2f8e94b786961bc27ac4" integrity sha512-nhRG8+RuG/L+0fAZBQYaRflXKjTrHOKH8MFTChnf+dNVMxA3wHYYrfj0tztK0W51ABXjGfRCDc0vRkecCOrsow== @@ -328,10 +357,10 @@ ansi-wrap@0.1.0: resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= -applicationinsights@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.6.tgz#bc201810de91cea910dab34e8ad35ecde488edeb" - integrity sha512-VQT3kBpJVPw5fCO5n+WUeSx0VHjxFtD7znYbILBlVgOS9/cMDuGFmV2Br3ObzFyZUDGNbEfW36fD1y2/vAiCKw== +applicationinsights@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" + integrity sha512-KzOOGdphOS/lXWMFZe5440LUdFbrLpMvh2SaRxn7BmiI550KAoSb2gIhiq6kJZ9Ir3AxRRztjhzif+e5P5IXIg== dependencies: diagnostic-channel "0.2.0" diagnostic-channel-publishers "0.2.1" @@ -344,16 +373,36 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +array-back@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + array-differ@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= +array-differ@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" + integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-uniq@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= +arrify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" @@ -481,6 +530,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + browserify-mime@~1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/browserify-mime/-/browserify-mime-1.2.9.tgz#aeb1af28de6c0d7a6a2ce40adb68ff18422af31f" @@ -512,7 +568,7 @@ chalk@^1.0.0, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.2.0, chalk@^2.3.0: +chalk@^2.3.0: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== @@ -548,6 +604,11 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= +code-block-writer@9.4.1: + version "9.4.1" + resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-9.4.1.tgz#1448fca79dfc7a3649000f4c85be6bc770604c4c" + integrity sha512-LHAB+DL4YZDcwK8y/kAxZ0Lf/ncwLh/Ux4cTVWbPwIdrf1gPxXiPcwpz8r8/KqXu1aD+Raz46EOxDjFlbyO6bA== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -584,6 +645,16 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" +command-line-args@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.1.1.tgz#88e793e5bb3ceb30754a86863f0401ac92fd369a" + integrity sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg== + dependencies: + array-back "^3.0.1" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + commander@^2.12.1, commander@^2.8.1: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" @@ -710,6 +781,13 @@ diff@^3.2.0: resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + documentdb@1.13.0: version "1.13.0" resolved "https://registry.yarnpkg.com/documentdb/-/documentdb-1.13.0.tgz#bba6f03150b2f42498cec4261bc439d834a33f8b" @@ -829,11 +907,30 @@ fast-deep-equal@^1.0.0: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= +fast-glob@^3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.0.4.tgz#d484a41005cb6faeb399b951fd1bd70ddaebb602" + integrity sha512-wkIbV6qg37xTJwqSsdnIphL1e+LaGz4AIQqr00mIubMaEhv1/HEmJ0uuCGZRNRUkZZmOB5mJKO0ZUTVq+SxMQg== + dependencies: + "@nodelib/fs.stat" "^2.0.1" + "@nodelib/fs.walk" "^1.2.1" + glob-parent "^5.0.0" + is-glob "^4.0.1" + merge2 "^1.2.3" + micromatch "^4.0.2" + fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= +fastq@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" + integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== + dependencies: + reusify "^1.0.0" + fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" @@ -841,6 +938,20 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -864,6 +975,15 @@ form-data@~2.3.1: combined-stream "1.0.6" mime-types "^2.1.12" +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -886,6 +1006,13 @@ github-releases@^0.4.1: prettyjson "1.2.1" request "2.81.0" +glob-parent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954" + integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg== + dependencies: + is-glob "^4.0.1" + glob@^7.0.6, glob@^7.1.1: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" @@ -898,6 +1025,32 @@ glob@^7.0.6, glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.3: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globby@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" + integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + glogg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" @@ -910,6 +1063,11 @@ graceful-fs@4.X: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" + integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== + gulp-bom@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gulp-bom/-/gulp-bom-1.0.0.tgz#38a183a07187bd57a7922d37977441f379df2abf" @@ -1086,6 +1244,11 @@ iconv-lite@0.4.23: dependencies: safer-buffer ">= 2.1.2 < 3" +ignore@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.2.tgz#e28e584d43ad7e92f96995019cc43b9e1ac49558" + integrity sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1094,21 +1257,75 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-negated-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" + integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= +is-windows@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -1171,6 +1388,13 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -1248,6 +1472,11 @@ lodash._root@^3.0.0: resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + lodash.escape@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" @@ -1331,6 +1560,19 @@ mdurl@^1.0.1: resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= +merge2@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" + integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + mime-db@~1.30.0: version "1.30.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" @@ -1382,6 +1624,17 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +multimatch@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3" + integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ== + dependencies: + "@types/minimatch" "^3.0.3" + array-differ "^3.0.0" + array-union "^2.1.0" + arrify "^2.0.1" + minimatch "^3.0.4" + multipipe@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" @@ -1480,6 +1733,11 @@ path-parse@^1.0.5: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" @@ -1495,6 +1753,11 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= +picomatch@^2.0.5: + version "2.0.7" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" + integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== + prettyjson@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-1.2.1.tgz#fcffab41d19cab4dfae5e575e64246619b12d289" @@ -1667,6 +1930,16 @@ resolve@^1.3.2: dependencies: path-parse "^1.0.5" +reusify@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + safe-buffer@^5.0.1, safe-buffer@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -1702,6 +1975,11 @@ semver@^5.1.0, semver@^5.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" @@ -1825,6 +2103,13 @@ tmp@0.0.29: dependencies: os-tmpdir "~1.0.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + tough-cookie@~2.3.0: version "2.3.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" @@ -1839,6 +2124,20 @@ tough-cookie@~2.3.3: dependencies: punycode "^1.4.1" +ts-morph@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-3.1.3.tgz#bbfa1d14481ee23bdd1c030340ccf4a243cfc844" + integrity sha512-CwjgyJTtd3f8vBi7Vr0IOgdOY6Wi/Tq0MhieXOE2B5ns5WWRD7BwMNHtv+ZufKI/S2U/lMrh+Q3bOauE4tsv2g== + dependencies: + "@dsherret/to-absolute-glob" "^2.0.2" + code-block-writer "9.4.1" + fs-extra "^8.1.0" + glob-parent "^5.0.0" + globby "^10.0.1" + is-negated-glob "^1.0.0" + multimatch "^4.0.0" + typescript "^3.0.1" + tslib@^1.8.0, tslib@^1.8.1: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" @@ -1894,16 +2193,31 @@ typed-rest-client@^0.9.0: tunnel "0.0.4" underscore "1.8.3" -typescript@3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.2.2.tgz#fe8101c46aa123f8353523ebdcf5730c2ae493e5" - integrity sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg== +typescript@3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.2.tgz#a09e1dc69bc9551cadf17dba10ee42cf55e5d56c" + integrity sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA== + +typescript@^3.0.1: + version "3.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" + integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376" integrity sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg== +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + underscore@1.8.3, underscore@~1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" @@ -1914,6 +2228,11 @@ underscore@^1.8.3: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" @@ -1994,6 +2313,20 @@ vsce@1.48.0: yauzl "^2.3.1" yazl "^2.2.2" +vscode-ripgrep@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.5.5.tgz#24c0e9cb356cf889c98e15ecb58f9cf654a1d961" + integrity sha512-OrPrAmcun4+uZAuNcQvE6CCPskh+5AsjANod/Q3zRcJcGNxgoOSGlQN9RPtatkUNmkN8Nn8mZBnS1jMylu/dKg== + +vscode-telemetry-extractor@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/vscode-telemetry-extractor/-/vscode-telemetry-extractor-1.5.3.tgz#c17f9065a47425edafd23ea161e80c23274e009d" + integrity sha512-feioJ1e1KyMa9rzblnLbSOduo+Ny0l62H3/bSDgfgCSnU/km+tTSYxPBvZHVr7iQfQGC95J61yC/ObqS9EbaQg== + dependencies: + command-line-args "^5.1.1" + ts-morph "^3.1.3" + vscode-ripgrep "^1.5.5" + vso-node-api@6.1.2-preview: version "6.1.2-preview" resolved "https://registry.yarnpkg.com/vso-node-api/-/vso-node-api-6.1.2-preview.tgz#aab3546df2451ecd894e071bb99b5df19c5fa78f" diff --git a/cglicenses.json b/cglicenses.json index 3d96813f3ef..b7f408109bf 100644 --- a/cglicenses.json +++ b/cglicenses.json @@ -6,694 +6,768 @@ // DO NOT EDIT THIS FILE UNLESS THE OSS TOOL INDICATES THAT YOU SHOULD. // [ -{ - // Reason: The license at https://github.com/aadsm/jschardet/blob/master/LICENSE - // does not include a clear Copyright statement and does not credit authors. - "name": "jschardet", - "licenseDetail": [ - "Chardet was originally ported from C++ by Mark Pilgrim. It is now maintained", - " by Dan Blanchard and Ian Cordasco, and was formerly maintained by Erik Rose.", - " JSChardet was ported from python to JavaScript by António Afonso ", - " (https://github.com/aadsm/jschardet) and transformed into an npm package by ", - "Markus Ast (https://github.com/brainafk)", - "", - "GNU LESSER GENERAL PUBLIC LICENSE", - "\t\t Version 2.1, February 1999", - "", - " Copyright (C) 1991,", - "1999 Free Software Foundation, Inc.", - " 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA", - " Everyone is permitted to copy and distribute verbatim copies", - " of this license document, but changing it is not allowed.", - "", - "[This is the first released version of the Lesser GPL. It also counts", - " as the successor of the GNU Library Public License, version 2, hence", - " the version number 2.1.", - "]", - "", - "\t\t\t Preamble", - "", - " The licenses for most software are designed to take away your", - "freedom to share and change it. By contrast, the GNU General Public", - "Licenses are intended to guarantee your freedom to share and change", - "free software--to make sure the software is free for all its users.", - "", - " This license, the Lesser General Public License, applies to some", - "specially designated software packages--typically libraries--of the", - "Free Software Foundation and other authors who decide to use it. You", - "can use it too, but we suggest you first think carefully about whether", - "this license or the ordinary General Public License is the better", - "strategy to use in any particular case, based on the explanations below.", - "", - " When we speak of free software, we are referring to freedom of use,", - "not price. Our General Public Licenses are designed to make sure that", - "you have the freedom to distribute copies of free software (and charge", - "for this service if you wish); that you receive source code or can get", - "it if you want it; that you can change the software and use pieces of", - "it in new free programs; and that you are informed that you can do", - "these things.", - "", - " To protect your rights, we need to make restrictions that forbid", - "distributors to deny you these rights or to ask you to surrender these", - "rights. These restrictions translate to certain responsibilities for", - "you if you distribute copies of the library or if you modify it.", - "", - " For example, if you distribute copies of the library, whether gratis", - "or for a fee, you must give the recipients all the rights that we gave", - "you. You must make sure that they, too, receive or can get the source", - "code. If you link other code with the library, you must provide", - "complete object files to the recipients, so that they can relink them", - "with the library after making changes to the library and recompiling", - "it. And you must show them these terms so they know their rights.", - "", - " We protect your rights with a two-step method: (1) we copyright the", - "library, and (2) we offer you this license, which gives you legal", - "permission to copy, distribute and/or modify the library.", - "", - " To protect each distributor, we want to make it very clear that", - "there is no warranty for the free library. Also, if the library is", - "modified by someone else and passed on, the recipients should know", - "that what they have is not the original version, so that the original", - "author's reputation will not be affected by problems that might be", - "introduced by others.", - "", - " Finally, software patents pose a constant threat to the existence of", - "any free program. We wish to make sure that a company cannot", - "effectively restrict the users of a free program by obtaining a", - "restrictive license from a patent holder. Therefore, we insist that", - "any patent license obtained for a version of the library must be", - "consistent with the full freedom of use specified in this license.", - "", - " Most GNU software, including some libraries, is covered by the", - "ordinary GNU General Public License. This license, the GNU Lesser", - "General Public License, applies to certain designated libraries, and", - "is quite different from the ordinary General Public License. We use", - "this license for certain libraries in order to permit linking those", - "libraries into non-free programs.", - "", - " When a program is linked with a library, whether statically or using", - "a shared library, the combination of the two is legally speaking a", - "combined work, a derivative of the original library. The ordinary", - "General Public License therefore permits such linking only if the", - "entire combination fits its criteria of freedom. The Lesser General", - "Public License permits more lax criteria for linking other code with", - "the library.", - "", - " We call this license the \"Lesser\" General Public License because it", - "does Less to protect the user's freedom than the ordinary General", - "Public License. It also provides other free software developers Less", - "of an advantage over competing non-free programs. These disadvantages", - "are the reason we use the ordinary General Public License for many", - "libraries. However, the Lesser license provides advantages in certain", - "special circumstances.", - "", - " For example, on rare occasions, there may be a special need to", - "encourage the widest possible use of a certain library, so that it becomes", - "a de-facto standard. To achieve this, non-free programs must be", - "allowed to use the library. A more frequent case is that a free", - "library does the same job as widely used non-free libraries. In this", - "case, there is little to gain by limiting the free library to free", - "software only, so we use the Lesser General Public License.", - "", - " In other cases, permission to use a particular library in non-free", - "programs enables a greater number of people to use a large body of", - "free software. For example, permission to use the GNU C Library in", - "non-free programs enables many more people to use the whole GNU", - "operating system, as well as its variant, the GNU/Linux operating", - "system.", - "", - " Although the Lesser General Public License is Less protective of the", - "users' freedom, it does ensure that the user of a program that is", - "linked with the Library has the freedom and the wherewithal to run", - "that program using a modified version of the Library.", - "", - " The precise terms and conditions for copying, distribution and", - "modification follow. Pay close attention to the difference between a", - "\"work based on the library\" and a \"work that uses the library\". The", - "former contains code derived from the library, whereas the latter must", - "be combined with the library in order to run.", - "", - "\t\t GNU LESSER GENERAL PUBLIC LICENSE", - " TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION", - "", - " 0. This License Agreement applies to any software library or other", - "program which contains a notice placed by the copyright holder or", - "other authorized party saying it may be distributed under the terms of", - "this Lesser General Public License (also called \"this License\").", - "Each licensee is addressed as \"you\".", - "", - " A \"library\" means a collection of software functions and/or data", - "prepared so as to be conveniently linked with application programs", - "(which use some of those functions and data) to form executables.", - "", - " The \"Library\", below, refers to any such software library or work", - "which has been distributed under these terms. A \"work based on the", - "Library\" means either the Library or any derivative work under", - "copyright law: that is to say, a work containing the Library or a", - "portion of it, either verbatim or with modifications and/or translated", - "straightforwardly into another language. (Hereinafter, translation is", - "included without limitation in the term \"modification\".)", - "", - " \"Source code\" for a work means the preferred form of the work for", - "making modifications to it. For a library, complete source code means", - "all the source code for all modules it contains, plus any associated", - "interface definition files, plus the scripts used to control compilation", - "and installation of the library.", - "", - " Activities other than copying, distribution and modification are not", - "covered by this License; they are outside its scope. The act of", - "running a program using the Library is not restricted, and output from", - "such a program is covered only if its contents constitute a work based", - "on the Library (independent of the use of the Library in a tool for", - "writing it). Whether that is true depends on what the Library does", - "and what the program that uses the Library does.", - "", - " 1. You may copy and distribute verbatim copies of the Library's", - "complete source code as you receive it, in any medium, provided that", - "you conspicuously and appropriately publish on each copy an", - "appropriate copyright notice and disclaimer of warranty; keep intact", - "all the notices that refer to this License and to the absence of any", - "warranty; and distribute a copy of this License along with the", - "Library.", - "", - " You may charge a fee for the physical act of transferring a copy,", - "and you may at your option offer warranty protection in exchange for a", - "fee.", - "", - " 2. You may modify your copy or copies of the Library or any portion", - "of it, thus forming a work based on the Library, and copy and", - "distribute such modifications or work under the terms of Section 1", - "above, provided that you also meet all of these conditions:", - "", - " a) The modified work must itself be a software library.", - "", - " b) You must cause the files modified to carry prominent notices", - " stating that you changed the files and the date of any change.", - "", - " c) You must cause the whole of the work to be licensed at no", - " charge to all third parties under the terms of this License.", - "", - " d) If a facility in the modified Library refers to a function or a", - " table of data to be supplied by an application program that uses", - " the facility, other than as an argument passed when the facility", - " is invoked, then you must make a good faith effort to ensure that,", - " in the event an application does not supply such function or", - " table, the facility still operates, and performs whatever part of", - " its purpose remains meaningful.", - "", - " (For example, a function in a library to compute square roots has", - " a purpose that is entirely well-defined independent of the", - " application. Therefore, Subsection 2d requires that any", - " application-supplied function or table used by this function must", - " be optional: if the application does not supply it, the square", - " root function must still compute square roots.)", - "", - "These requirements apply to the modified work as a whole. If", - "identifiable sections of that work are not derived from the Library,", - "and can be reasonably considered independent and separate works in", - "themselves, then this License, and its terms, do not apply to those", - "sections when you distribute them as separate works. But when you", - "distribute the same sections as part of a whole which is a work based", - "on the Library, the distribution of the whole must be on the terms of", - "this License, whose permissions for other licensees extend to the", - "entire whole, and thus to each and every part regardless of who wrote", - "it.", - "", - "Thus, it is not the intent of this section to claim rights or contest", - "your rights to work written entirely by you; rather, the intent is to", - "exercise the right to control the distribution of derivative or", - "collective works based on the Library.", - "", - "In addition, mere aggregation of another work not based on the Library", - "with the Library (or with a work based on the Library) on a volume of", - "a storage or distribution medium does not bring the other work under", - "the scope of this License.", - "", - " 3. You may opt to apply the terms of the ordinary GNU General Public", - "License instead of this License to a given copy of the Library. To do", - "this, you must alter all the notices that refer to this License, so", - "that they refer to the ordinary GNU General Public License, version 2,", - "instead of to this License. (If a newer version than version 2 of the", - "ordinary GNU General Public License has appeared, then you can specify", - "that version instead if you wish.) Do not make any other change in", - "these notices.", - "", - " Once this change is made in a given copy, it is irreversible for", - "that copy, so the ordinary GNU General Public License applies to all", - "subsequent copies and derivative works made from that copy.", - "", - " This option is useful when you wish to copy part of the code of", - "the Library into a program that is not a library.", - "", - " 4. You may copy and distribute the Library (or a portion or", - "derivative of it, under Section 2) in object code or executable form", - "under the terms of Sections 1 and 2 above provided that you accompany", - "it with the complete corresponding machine-readable source code, which", - "must be distributed under the terms of Sections 1 and 2 above on a", - "medium customarily used for software interchange.", - "", - " If distribution of object code is made by offering access to copy", - "from a designated place, then offering equivalent access to copy the", - "source code from the same place satisfies the requirement to", - "distribute the source code, even though third parties are not", - "compelled to copy the source along with the object code.", - "", - " 5. A program that contains no derivative of any portion of the", - "Library, but is designed to work with the Library by being compiled or", - "linked with it, is called a \"work that uses the Library\". Such a", - "work, in isolation, is not a derivative work of the Library, and", - "therefore falls outside the scope of this License.", - "", - " However, linking a \"work that uses the Library\" with the Library", - "creates an executable that is a derivative of the Library (because it", - "contains portions of the Library), rather than a \"work that uses the", - "library\". The executable is therefore covered by this License.", - "Section 6 states terms for distribution of such executables.", - "", - " When a \"work that uses the Library\" uses material from a header file", - "that is part of the Library, the object code for the work may be a", - "derivative work of the Library even though the source code is not.", - "Whether this is true is especially significant if the work can be", - "linked without the Library, or if the work is itself a library. The", - "threshold for this to be true is not precisely defined by law.", - "", - " If such an object file uses only numerical parameters, data", - "structure layouts and accessors, and small macros and small inline", - "functions (ten lines or less in length), then the use of the object", - "file is unrestricted, regardless of whether it is legally a derivative", - "work. (Executables containing this object code plus portions of the", - "Library will still fall under Section 6.)", - "", - " Otherwise, if the work is a derivative of the Library, you may", - "distribute the object code for the work under the terms of Section 6.", - "Any executables containing that work also fall under Section 6,", - "whether or not they are linked directly with the Library itself.", - "", - " 6. As an exception to the Sections above, you may also combine or", - "link a \"work that uses the Library\" with the Library to produce a", - "work containing portions of the Library, and distribute that work", - "under terms of your choice, provided that the terms permit", - "modification of the work for the customer's own use and reverse", - "engineering for debugging such modifications.", - "", - " You must give prominent notice with each copy of the work that the", - "Library is used in it and that the Library and its use are covered by", - "this License. You must supply a copy of this License. If the work", - "during execution displays copyright notices, you must include the", - "copyright notice for the Library among them, as well as a reference", - "directing the user to the copy of this License. Also, you must do one", - "of these things:", - "", - " a) Accompany the work with the complete corresponding", - " machine-readable source code for the Library including whatever", - " changes were used in the work (which must be distributed under", - " Sections 1 and 2 above); and, if the work is an executable linked", - " with the Library, with the complete machine-readable \"work that", - " uses the Library\", as object code and/or source code, so that the", - " user can modify the Library and then relink to produce a modified", - " executable containing the modified Library. (It is understood", - " that the user who changes the contents of definitions files in the", - " Library will not necessarily be able to recompile the application", - " to use the modified definitions.)", - "", - " b) Use a suitable shared library mechanism for linking with the", - " Library. A suitable mechanism is one that (1) uses at run time a", - " copy of the library already present on the user's computer system,", - " rather than copying library functions into the executable, and (2)", - " will operate properly with a modified version of the library, if", - " the user installs one, as long as the modified version is", - " interface-compatible with the version that the work was made with.", - "", - " c) Accompany the work with a written offer, valid for at", - " least three years, to give the same user the materials", - " specified in Subsection 6a, above, for a charge no more", - " than the cost of performing this distribution.", - "", - " d) If distribution of the work is made by offering access to copy", - " from a designated place, offer equivalent access to copy the above", - " specified materials from the same place.", - "", - " e) Verify that the user has already received a copy of these", - " materials or that you have already sent this user a copy.", - "", - " For an executable, the required form of the \"work that uses the", - "Library\" must include any data and utility programs needed for", - "reproducing the executable from it. However, as a special exception,", - "the materials to be distributed need not include anything that is", - "normally distributed (in either source or binary form) with the major", - "components (compiler, kernel, and so on) of the operating system on", - "which the executable runs, unless that component itself accompanies", - "the executable.", - "", - " It may happen that this requirement contradicts the license", - "restrictions of other proprietary libraries that do not normally", - "accompany the operating system. Such a contradiction means you cannot", - "use both them and the Library together in an executable that you", - "distribute.", - "", - " 7. You may place library facilities that are a work based on the", - "Library side-by-side in a single library together with other library", - "facilities not covered by this License, and distribute such a combined", - "library, provided that the separate distribution of the work based on", - "the Library and of the other library facilities is otherwise", - "permitted, and provided that you do these two things:", - "", - " a) Accompany the combined library with a copy of the same work", - " based on the Library, uncombined with any other library", - " facilities. This must be distributed under the terms of the", - " Sections above.", - "", - " b) Give prominent notice with the combined library of the fact", - " that part of it is a work based on the Library, and explaining", - " where to find the accompanying uncombined form of the same work.", - "", - " 8. You may not copy, modify, sublicense, link with, or distribute", - "the Library except as expressly provided under this License. Any", - "attempt otherwise to copy, modify, sublicense, link with, or", - "distribute the Library is void, and will automatically terminate your", - "rights under this License. However, parties who have received copies,", - "or rights, from you under this License will not have their licenses", - "terminated so long as such parties remain in full compliance.", - "", - " 9. You are not required to accept this License, since you have not", - "signed it. However, nothing else grants you permission to modify or", - "distribute the Library or its derivative works. These actions are", - "prohibited by law if you do not accept this License. Therefore, by", - "modifying or distributing the Library (or any work based on the", - "Library), you indicate your acceptance of this License to do so, and", - "all its terms and conditions for copying, distributing or modifying", - "the Library or works based on it.", - "", - " 10. Each time you redistribute the Library (or any work based on the", - "Library), the recipient automatically receives a license from the", - "original licensor to copy, distribute, link with or modify the Library", - "subject to these terms and conditions. You may not impose any further", - "restrictions on the recipients' exercise of the rights granted herein.", - "You are not responsible for enforcing compliance by third parties with", - "this License.", - "", - " 11. If, as a consequence of a court judgment or allegation of patent", - "infringement or for any other reason (not limited to patent issues),", - "conditions are imposed on you (whether by court order, agreement or", - "otherwise) that contradict the conditions of this License, they do not", - "excuse you from the conditions of this License. If you cannot", - "distribute so as to satisfy simultaneously your obligations under this", - "License and any other pertinent obligations, then as a consequence you", - "may not distribute the Library at all. For example, if a patent", - "license would not permit royalty-free redistribution of the Library by", - "all those who receive copies directly or indirectly through you, then", - "the only way you could satisfy both it and this License would be to", - "refrain entirely from distribution of the Library.", - "", - "If any portion of this section is held invalid or unenforceable under any", - "particular circumstance, the balance of the section is intended to apply,", - "and the section as a whole is intended to apply in other circumstances.", - "", - "It is not the purpose of this section to induce you to infringe any", - "patents or other property right claims or to contest validity of any", - "such claims; this section has the sole purpose of protecting the", - "integrity of the free software distribution system which is", - "implemented by public license practices. Many people have made", - "generous contributions to the wide range of software distributed", - "through that system in reliance on consistent application of that", - "system; it is up to the author/donor to decide if he or she is willing", - "to distribute software through any other system and a licensee cannot", - "impose that choice.", - "", - "This section is intended to make thoroughly clear what is believed to", - "be a consequence of the rest of this License.", - "", - " 12. If the distribution and/or use of the Library is restricted in", - "certain countries either by patents or by copyrighted interfaces, the", - "original copyright holder who places the Library under this License may add", - "an explicit geographical distribution limitation excluding those countries,", - "so that distribution is permitted only in or among countries not thus", - "excluded. In such case, this License incorporates the limitation as if", - "written in the body of this License.", - "", - " 13. The Free Software Foundation may publish revised and/or new", - "versions of the Lesser General Public License from time to time.", - "Such new versions will be similar in spirit to the present version,", - "but may differ in detail to address new problems or concerns.", - "", - "Each version is given a distinguishing version number. If the Library", - "specifies a version number of this License which applies to it and", - "\"any later version\", you have the option of following the terms and", - "conditions either of that version or of any later version published by", - "the Free Software Foundation. If the Library does not specify a", - "license version number, you may choose any version ever published by", - "the Free Software Foundation.", - "", - " 14. If you wish to incorporate parts of the Library into other free", - "programs whose distribution conditions are incompatible with these,", - "write to the author to ask for permission. For software which is", - "copyrighted by the Free Software Foundation, write to the Free", - "Software Foundation; we sometimes make exceptions for this. Our", - "decision will be guided by the two goals of preserving the free status", - "of all derivatives of our free software and of promoting the sharing", - "and reuse of software generally.", - "", - "\t\t\t NO WARRANTY", - "", - " 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO", - "WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.", - "EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR", - "OTHER PARTIES PROVIDE THE LIBRARY \"AS IS\" WITHOUT WARRANTY OF ANY", - "KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE", - "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR", - "PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE", - "LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME", - "THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.", - "", - " 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN", - "WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY", - "AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU", - "FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR", - "CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE", - "LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING", - "RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A", - "FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF", - "SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH", - "DAMAGES.", - "", - "\t\t END OF TERMS AND CONDITIONS", - "", - " How to Apply These Terms to Your New Libraries", - "", - " If you develop a new library, and you want it to be of the greatest", - "possible use to the public, we recommend making it free software that", - "everyone can redistribute and change. You can do so by permitting", - "redistribution under these terms (or, alternatively, under the terms of the", - "ordinary General Public License).", - "", - " To apply these terms, attach the following notices to the library. It is", - "safest to attach them to the start of each source file to most effectively", - "convey the exclusion of warranty; and each file should have at least the", - "\"copyright\" line and a pointer to where the full notice is found.", - "", - " ", - " Copyright (C) ", - "", - " This library is free software; you can redistribute it and/or", - " modify it under the terms of the GNU Lesser General Public", - " License as published by the Free Software Foundation; either", - " version 2.1 of the License, or (at your option) any later version.", - "", - " This library is distributed in the hope that it will be useful,", - " but WITHOUT ANY WARRANTY; without even the implied warranty of", - " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU", - " Lesser General Public License for more details.", - "", - " You should have received a copy of the GNU Lesser General Public", - " License along with this library; if not, write to the Free Software", - " Foundation, Inc.,", - "51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA", - "", - "Also add information on how to contact you by electronic and paper mail.", - "", - "You should also get your employer (if you work as a programmer) or your", - "school, if any, to sign a \"copyright disclaimer\" for the library, if", - "necessary. Here is a sample; alter the names:", - "", - " Yoyodyne, Inc., hereby disclaims all copyright interest in the", - " library `Frob' (a library for tweaking knobs) written by James Random Hacker.", - "", - " ,", - "1 April 1990", - " Ty Coon, President of Vice", - "", - "That's all there is to it!" - ] -}, -{ - // Added here because the module `parse5` has a dependency to it. - // The module `parse5` is shipped via the `extension-editing` built-in extension. - // The module `parse5` does not want to remove it https://github.com/inikulin/parse5/issues/225 - "name": "@types/node", - "licenseDetail": [ - "This project is licensed under the MIT license.", - "Copyrights are respective of each contributor listed at the beginning of each definition file.", - "", - "Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:", - "", - "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.", - "", - "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." - ] -}, -{ - // We override the license that gets discovered at - // https://github.com/Microsoft/TypeScript/blob/master/LICENSE.txt - // because it does not contain a Copyright statement - "name": "typescript", - "licenseDetail": [ - "Copyright (c) Microsoft Corporation. All rights reserved.", - "", - "Apache License", - "", - "Version 2.0, January 2004", - "", - "http://www.apache.org/licenses/", - "", - "TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION", - "", - "1. Definitions.", - "", - "\"License\" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.", - "", - "\"Licensor\" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.", - "", - "\"Legal Entity\" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, \"control\" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.", - "", - "\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising permissions granted by this License.", - "", - "\"Source\" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.", - "", - "\"Object\" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.", - "", - "\"Work\" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).", - "", - "\"Derivative Works\" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.", - "", - "\"Contribution\" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, \"submitted\" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as \"Not a Contribution.\"", - "", - "\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.", - "", - "2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.", - "", - "3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.", - "", - "4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:", - "", - "You must give any other recipients of the Work or Derivative Works a copy of this License; and", - "", - "You must cause any modified files to carry prominent notices stating that You changed the files; and", - "", - "You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and", - "", - "If the Work includes a \"NOTICE\" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.", - "", - "5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.", - "", - "6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.", - "", - "7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.", - "", - "8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.", - "", - "9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.", - "", - "END OF TERMS AND CONDITIONS" - ] -}, -{ - // This module comes in from https://github.com/Microsoft/vscode-node-debug2/blob/master/package-lock.json - "name": "@types/source-map", - "licenseDetail": [ - "This project is licensed under the MIT license.", - "Copyrights are respective of each contributor listed at the beginning of each definition file.", - "", - "Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:", - "", - "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.", - "", - "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." - ] -}, -{ - "name": "tunnel-agent", - "licenseDetail": [ - "Copyright (c) tunnel-agent authors", - "", - "Apache License", - "", - "Version 2.0, January 2004", - "", - "http://www.apache.org/licenses/", - "", - "TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION", - "", - "1. Definitions.", - "", - "\"License\" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.", - "", - "\"Licensor\" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.", - "", - "\"Legal Entity\" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, \"control\" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.", - "", - "\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising permissions granted by this License.", - "", - "\"Source\" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.", - "", - "\"Object\" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.", - "", - "\"Work\" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).", - "", - "\"Derivative Works\" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.", - "", - "\"Contribution\" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, \"submitted\" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as \"Not a Contribution.\"", - "", - "\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.", - "", - "2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.", - "", - "3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.", - "", - "4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:", - "", - "You must give any other recipients of the Work or Derivative Works a copy of this License; and", - "", - "You must cause any modified files to carry prominent notices stating that You changed the files; and", - "", - "You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and", - "", - "If the Work includes a \"NOTICE\" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.", - "", - "5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.", - "", - "6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.", - "", - "7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.", - "", - "8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.", - "", - "9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.", - "", - "END OF TERMS AND CONDITIONS" - ] -}, -{ - // Waiting for https://github.com/segmentio/noop-logger/issues/2 - "name": "noop-logger", - "licenseDetail": [ - "This project is licensed under the MIT license.", - "Copyrights are respective of each contributor listed at the beginning of each definition file.", - "", - "Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:", - "", - "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.", - "", - "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." - ] -} -] \ No newline at end of file + { + // Reason: The license at https://github.com/aadsm/jschardet/blob/master/LICENSE + // does not include a clear Copyright statement and does not credit authors. + "name": "jschardet", + "licenseDetail": [ + "Chardet was originally ported from C++ by Mark Pilgrim. It is now maintained", + " by Dan Blanchard and Ian Cordasco, and was formerly maintained by Erik Rose.", + " JSChardet was ported from python to JavaScript by António Afonso ", + " (https://github.com/aadsm/jschardet) and transformed into an npm package by ", + "Markus Ast (https://github.com/brainafk)", + "", + "GNU LESSER GENERAL PUBLIC LICENSE", + "\t\t Version 2.1, February 1999", + "", + " Copyright (C) 1991,", + "1999 Free Software Foundation, Inc.", + " 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA", + " Everyone is permitted to copy and distribute verbatim copies", + " of this license document, but changing it is not allowed.", + "", + "[This is the first released version of the Lesser GPL. It also counts", + " as the successor of the GNU Library Public License, version 2, hence", + " the version number 2.1.", + "]", + "", + "\t\t\t Preamble", + "", + " The licenses for most software are designed to take away your", + "freedom to share and change it. By contrast, the GNU General Public", + "Licenses are intended to guarantee your freedom to share and change", + "free software--to make sure the software is free for all its users.", + "", + " This license, the Lesser General Public License, applies to some", + "specially designated software packages--typically libraries--of the", + "Free Software Foundation and other authors who decide to use it. You", + "can use it too, but we suggest you first think carefully about whether", + "this license or the ordinary General Public License is the better", + "strategy to use in any particular case, based on the explanations below.", + "", + " When we speak of free software, we are referring to freedom of use,", + "not price. Our General Public Licenses are designed to make sure that", + "you have the freedom to distribute copies of free software (and charge", + "for this service if you wish); that you receive source code or can get", + "it if you want it; that you can change the software and use pieces of", + "it in new free programs; and that you are informed that you can do", + "these things.", + "", + " To protect your rights, we need to make restrictions that forbid", + "distributors to deny you these rights or to ask you to surrender these", + "rights. These restrictions translate to certain responsibilities for", + "you if you distribute copies of the library or if you modify it.", + "", + " For example, if you distribute copies of the library, whether gratis", + "or for a fee, you must give the recipients all the rights that we gave", + "you. You must make sure that they, too, receive or can get the source", + "code. If you link other code with the library, you must provide", + "complete object files to the recipients, so that they can relink them", + "with the library after making changes to the library and recompiling", + "it. And you must show them these terms so they know their rights.", + "", + " We protect your rights with a two-step method: (1) we copyright the", + "library, and (2) we offer you this license, which gives you legal", + "permission to copy, distribute and/or modify the library.", + "", + " To protect each distributor, we want to make it very clear that", + "there is no warranty for the free library. Also, if the library is", + "modified by someone else and passed on, the recipients should know", + "that what they have is not the original version, so that the original", + "author's reputation will not be affected by problems that might be", + "introduced by others.", + "", + " Finally, software patents pose a constant threat to the existence of", + "any free program. We wish to make sure that a company cannot", + "effectively restrict the users of a free program by obtaining a", + "restrictive license from a patent holder. Therefore, we insist that", + "any patent license obtained for a version of the library must be", + "consistent with the full freedom of use specified in this license.", + "", + " Most GNU software, including some libraries, is covered by the", + "ordinary GNU General Public License. This license, the GNU Lesser", + "General Public License, applies to certain designated libraries, and", + "is quite different from the ordinary General Public License. We use", + "this license for certain libraries in order to permit linking those", + "libraries into non-free programs.", + "", + " When a program is linked with a library, whether statically or using", + "a shared library, the combination of the two is legally speaking a", + "combined work, a derivative of the original library. The ordinary", + "General Public License therefore permits such linking only if the", + "entire combination fits its criteria of freedom. The Lesser General", + "Public License permits more lax criteria for linking other code with", + "the library.", + "", + " We call this license the \"Lesser\" General Public License because it", + "does Less to protect the user's freedom than the ordinary General", + "Public License. It also provides other free software developers Less", + "of an advantage over competing non-free programs. These disadvantages", + "are the reason we use the ordinary General Public License for many", + "libraries. However, the Lesser license provides advantages in certain", + "special circumstances.", + "", + " For example, on rare occasions, there may be a special need to", + "encourage the widest possible use of a certain library, so that it becomes", + "a de-facto standard. To achieve this, non-free programs must be", + "allowed to use the library. A more frequent case is that a free", + "library does the same job as widely used non-free libraries. In this", + "case, there is little to gain by limiting the free library to free", + "software only, so we use the Lesser General Public License.", + "", + " In other cases, permission to use a particular library in non-free", + "programs enables a greater number of people to use a large body of", + "free software. For example, permission to use the GNU C Library in", + "non-free programs enables many more people to use the whole GNU", + "operating system, as well as its variant, the GNU/Linux operating", + "system.", + "", + " Although the Lesser General Public License is Less protective of the", + "users' freedom, it does ensure that the user of a program that is", + "linked with the Library has the freedom and the wherewithal to run", + "that program using a modified version of the Library.", + "", + " The precise terms and conditions for copying, distribution and", + "modification follow. Pay close attention to the difference between a", + "\"work based on the library\" and a \"work that uses the library\". The", + "former contains code derived from the library, whereas the latter must", + "be combined with the library in order to run.", + "", + "\t\t GNU LESSER GENERAL PUBLIC LICENSE", + " TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION", + "", + " 0. This License Agreement applies to any software library or other", + "program which contains a notice placed by the copyright holder or", + "other authorized party saying it may be distributed under the terms of", + "this Lesser General Public License (also called \"this License\").", + "Each licensee is addressed as \"you\".", + "", + " A \"library\" means a collection of software functions and/or data", + "prepared so as to be conveniently linked with application programs", + "(which use some of those functions and data) to form executables.", + "", + " The \"Library\", below, refers to any such software library or work", + "which has been distributed under these terms. A \"work based on the", + "Library\" means either the Library or any derivative work under", + "copyright law: that is to say, a work containing the Library or a", + "portion of it, either verbatim or with modifications and/or translated", + "straightforwardly into another language. (Hereinafter, translation is", + "included without limitation in the term \"modification\".)", + "", + " \"Source code\" for a work means the preferred form of the work for", + "making modifications to it. For a library, complete source code means", + "all the source code for all modules it contains, plus any associated", + "interface definition files, plus the scripts used to control compilation", + "and installation of the library.", + "", + " Activities other than copying, distribution and modification are not", + "covered by this License; they are outside its scope. The act of", + "running a program using the Library is not restricted, and output from", + "such a program is covered only if its contents constitute a work based", + "on the Library (independent of the use of the Library in a tool for", + "writing it). Whether that is true depends on what the Library does", + "and what the program that uses the Library does.", + "", + " 1. You may copy and distribute verbatim copies of the Library's", + "complete source code as you receive it, in any medium, provided that", + "you conspicuously and appropriately publish on each copy an", + "appropriate copyright notice and disclaimer of warranty; keep intact", + "all the notices that refer to this License and to the absence of any", + "warranty; and distribute a copy of this License along with the", + "Library.", + "", + " You may charge a fee for the physical act of transferring a copy,", + "and you may at your option offer warranty protection in exchange for a", + "fee.", + "", + " 2. You may modify your copy or copies of the Library or any portion", + "of it, thus forming a work based on the Library, and copy and", + "distribute such modifications or work under the terms of Section 1", + "above, provided that you also meet all of these conditions:", + "", + " a) The modified work must itself be a software library.", + "", + " b) You must cause the files modified to carry prominent notices", + " stating that you changed the files and the date of any change.", + "", + " c) You must cause the whole of the work to be licensed at no", + " charge to all third parties under the terms of this License.", + "", + " d) If a facility in the modified Library refers to a function or a", + " table of data to be supplied by an application program that uses", + " the facility, other than as an argument passed when the facility", + " is invoked, then you must make a good faith effort to ensure that,", + " in the event an application does not supply such function or", + " table, the facility still operates, and performs whatever part of", + " its purpose remains meaningful.", + "", + " (For example, a function in a library to compute square roots has", + " a purpose that is entirely well-defined independent of the", + " application. Therefore, Subsection 2d requires that any", + " application-supplied function or table used by this function must", + " be optional: if the application does not supply it, the square", + " root function must still compute square roots.)", + "", + "These requirements apply to the modified work as a whole. If", + "identifiable sections of that work are not derived from the Library,", + "and can be reasonably considered independent and separate works in", + "themselves, then this License, and its terms, do not apply to those", + "sections when you distribute them as separate works. But when you", + "distribute the same sections as part of a whole which is a work based", + "on the Library, the distribution of the whole must be on the terms of", + "this License, whose permissions for other licensees extend to the", + "entire whole, and thus to each and every part regardless of who wrote", + "it.", + "", + "Thus, it is not the intent of this section to claim rights or contest", + "your rights to work written entirely by you; rather, the intent is to", + "exercise the right to control the distribution of derivative or", + "collective works based on the Library.", + "", + "In addition, mere aggregation of another work not based on the Library", + "with the Library (or with a work based on the Library) on a volume of", + "a storage or distribution medium does not bring the other work under", + "the scope of this License.", + "", + " 3. You may opt to apply the terms of the ordinary GNU General Public", + "License instead of this License to a given copy of the Library. To do", + "this, you must alter all the notices that refer to this License, so", + "that they refer to the ordinary GNU General Public License, version 2,", + "instead of to this License. (If a newer version than version 2 of the", + "ordinary GNU General Public License has appeared, then you can specify", + "that version instead if you wish.) Do not make any other change in", + "these notices.", + "", + " Once this change is made in a given copy, it is irreversible for", + "that copy, so the ordinary GNU General Public License applies to all", + "subsequent copies and derivative works made from that copy.", + "", + " This option is useful when you wish to copy part of the code of", + "the Library into a program that is not a library.", + "", + " 4. You may copy and distribute the Library (or a portion or", + "derivative of it, under Section 2) in object code or executable form", + "under the terms of Sections 1 and 2 above provided that you accompany", + "it with the complete corresponding machine-readable source code, which", + "must be distributed under the terms of Sections 1 and 2 above on a", + "medium customarily used for software interchange.", + "", + " If distribution of object code is made by offering access to copy", + "from a designated place, then offering equivalent access to copy the", + "source code from the same place satisfies the requirement to", + "distribute the source code, even though third parties are not", + "compelled to copy the source along with the object code.", + "", + " 5. A program that contains no derivative of any portion of the", + "Library, but is designed to work with the Library by being compiled or", + "linked with it, is called a \"work that uses the Library\". Such a", + "work, in isolation, is not a derivative work of the Library, and", + "therefore falls outside the scope of this License.", + "", + " However, linking a \"work that uses the Library\" with the Library", + "creates an executable that is a derivative of the Library (because it", + "contains portions of the Library), rather than a \"work that uses the", + "library\". The executable is therefore covered by this License.", + "Section 6 states terms for distribution of such executables.", + "", + " When a \"work that uses the Library\" uses material from a header file", + "that is part of the Library, the object code for the work may be a", + "derivative work of the Library even though the source code is not.", + "Whether this is true is especially significant if the work can be", + "linked without the Library, or if the work is itself a library. The", + "threshold for this to be true is not precisely defined by law.", + "", + " If such an object file uses only numerical parameters, data", + "structure layouts and accessors, and small macros and small inline", + "functions (ten lines or less in length), then the use of the object", + "file is unrestricted, regardless of whether it is legally a derivative", + "work. (Executables containing this object code plus portions of the", + "Library will still fall under Section 6.)", + "", + " Otherwise, if the work is a derivative of the Library, you may", + "distribute the object code for the work under the terms of Section 6.", + "Any executables containing that work also fall under Section 6,", + "whether or not they are linked directly with the Library itself.", + "", + " 6. As an exception to the Sections above, you may also combine or", + "link a \"work that uses the Library\" with the Library to produce a", + "work containing portions of the Library, and distribute that work", + "under terms of your choice, provided that the terms permit", + "modification of the work for the customer's own use and reverse", + "engineering for debugging such modifications.", + "", + " You must give prominent notice with each copy of the work that the", + "Library is used in it and that the Library and its use are covered by", + "this License. You must supply a copy of this License. If the work", + "during execution displays copyright notices, you must include the", + "copyright notice for the Library among them, as well as a reference", + "directing the user to the copy of this License. Also, you must do one", + "of these things:", + "", + " a) Accompany the work with the complete corresponding", + " machine-readable source code for the Library including whatever", + " changes were used in the work (which must be distributed under", + " Sections 1 and 2 above); and, if the work is an executable linked", + " with the Library, with the complete machine-readable \"work that", + " uses the Library\", as object code and/or source code, so that the", + " user can modify the Library and then relink to produce a modified", + " executable containing the modified Library. (It is understood", + " that the user who changes the contents of definitions files in the", + " Library will not necessarily be able to recompile the application", + " to use the modified definitions.)", + "", + " b) Use a suitable shared library mechanism for linking with the", + " Library. A suitable mechanism is one that (1) uses at run time a", + " copy of the library already present on the user's computer system,", + " rather than copying library functions into the executable, and (2)", + " will operate properly with a modified version of the library, if", + " the user installs one, as long as the modified version is", + " interface-compatible with the version that the work was made with.", + "", + " c) Accompany the work with a written offer, valid for at", + " least three years, to give the same user the materials", + " specified in Subsection 6a, above, for a charge no more", + " than the cost of performing this distribution.", + "", + " d) If distribution of the work is made by offering access to copy", + " from a designated place, offer equivalent access to copy the above", + " specified materials from the same place.", + "", + " e) Verify that the user has already received a copy of these", + " materials or that you have already sent this user a copy.", + "", + " For an executable, the required form of the \"work that uses the", + "Library\" must include any data and utility programs needed for", + "reproducing the executable from it. However, as a special exception,", + "the materials to be distributed need not include anything that is", + "normally distributed (in either source or binary form) with the major", + "components (compiler, kernel, and so on) of the operating system on", + "which the executable runs, unless that component itself accompanies", + "the executable.", + "", + " It may happen that this requirement contradicts the license", + "restrictions of other proprietary libraries that do not normally", + "accompany the operating system. Such a contradiction means you cannot", + "use both them and the Library together in an executable that you", + "distribute.", + "", + " 7. You may place library facilities that are a work based on the", + "Library side-by-side in a single library together with other library", + "facilities not covered by this License, and distribute such a combined", + "library, provided that the separate distribution of the work based on", + "the Library and of the other library facilities is otherwise", + "permitted, and provided that you do these two things:", + "", + " a) Accompany the combined library with a copy of the same work", + " based on the Library, uncombined with any other library", + " facilities. This must be distributed under the terms of the", + " Sections above.", + "", + " b) Give prominent notice with the combined library of the fact", + " that part of it is a work based on the Library, and explaining", + " where to find the accompanying uncombined form of the same work.", + "", + " 8. You may not copy, modify, sublicense, link with, or distribute", + "the Library except as expressly provided under this License. Any", + "attempt otherwise to copy, modify, sublicense, link with, or", + "distribute the Library is void, and will automatically terminate your", + "rights under this License. However, parties who have received copies,", + "or rights, from you under this License will not have their licenses", + "terminated so long as such parties remain in full compliance.", + "", + " 9. You are not required to accept this License, since you have not", + "signed it. However, nothing else grants you permission to modify or", + "distribute the Library or its derivative works. These actions are", + "prohibited by law if you do not accept this License. Therefore, by", + "modifying or distributing the Library (or any work based on the", + "Library), you indicate your acceptance of this License to do so, and", + "all its terms and conditions for copying, distributing or modifying", + "the Library or works based on it.", + "", + " 10. Each time you redistribute the Library (or any work based on the", + "Library), the recipient automatically receives a license from the", + "original licensor to copy, distribute, link with or modify the Library", + "subject to these terms and conditions. You may not impose any further", + "restrictions on the recipients' exercise of the rights granted herein.", + "You are not responsible for enforcing compliance by third parties with", + "this License.", + "", + " 11. If, as a consequence of a court judgment or allegation of patent", + "infringement or for any other reason (not limited to patent issues),", + "conditions are imposed on you (whether by court order, agreement or", + "otherwise) that contradict the conditions of this License, they do not", + "excuse you from the conditions of this License. If you cannot", + "distribute so as to satisfy simultaneously your obligations under this", + "License and any other pertinent obligations, then as a consequence you", + "may not distribute the Library at all. For example, if a patent", + "license would not permit royalty-free redistribution of the Library by", + "all those who receive copies directly or indirectly through you, then", + "the only way you could satisfy both it and this License would be to", + "refrain entirely from distribution of the Library.", + "", + "If any portion of this section is held invalid or unenforceable under any", + "particular circumstance, the balance of the section is intended to apply,", + "and the section as a whole is intended to apply in other circumstances.", + "", + "It is not the purpose of this section to induce you to infringe any", + "patents or other property right claims or to contest validity of any", + "such claims; this section has the sole purpose of protecting the", + "integrity of the free software distribution system which is", + "implemented by public license practices. Many people have made", + "generous contributions to the wide range of software distributed", + "through that system in reliance on consistent application of that", + "system; it is up to the author/donor to decide if he or she is willing", + "to distribute software through any other system and a licensee cannot", + "impose that choice.", + "", + "This section is intended to make thoroughly clear what is believed to", + "be a consequence of the rest of this License.", + "", + " 12. If the distribution and/or use of the Library is restricted in", + "certain countries either by patents or by copyrighted interfaces, the", + "original copyright holder who places the Library under this License may add", + "an explicit geographical distribution limitation excluding those countries,", + "so that distribution is permitted only in or among countries not thus", + "excluded. In such case, this License incorporates the limitation as if", + "written in the body of this License.", + "", + " 13. The Free Software Foundation may publish revised and/or new", + "versions of the Lesser General Public License from time to time.", + "Such new versions will be similar in spirit to the present version,", + "but may differ in detail to address new problems or concerns.", + "", + "Each version is given a distinguishing version number. If the Library", + "specifies a version number of this License which applies to it and", + "\"any later version\", you have the option of following the terms and", + "conditions either of that version or of any later version published by", + "the Free Software Foundation. If the Library does not specify a", + "license version number, you may choose any version ever published by", + "the Free Software Foundation.", + "", + " 14. If you wish to incorporate parts of the Library into other free", + "programs whose distribution conditions are incompatible with these,", + "write to the author to ask for permission. For software which is", + "copyrighted by the Free Software Foundation, write to the Free", + "Software Foundation; we sometimes make exceptions for this. Our", + "decision will be guided by the two goals of preserving the free status", + "of all derivatives of our free software and of promoting the sharing", + "and reuse of software generally.", + "", + "\t\t\t NO WARRANTY", + "", + " 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO", + "WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.", + "EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR", + "OTHER PARTIES PROVIDE THE LIBRARY \"AS IS\" WITHOUT WARRANTY OF ANY", + "KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE", + "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR", + "PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE", + "LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME", + "THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.", + "", + " 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN", + "WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY", + "AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU", + "FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR", + "CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE", + "LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING", + "RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A", + "FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF", + "SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH", + "DAMAGES.", + "", + "\t\t END OF TERMS AND CONDITIONS", + "", + " How to Apply These Terms to Your New Libraries", + "", + " If you develop a new library, and you want it to be of the greatest", + "possible use to the public, we recommend making it free software that", + "everyone can redistribute and change. You can do so by permitting", + "redistribution under these terms (or, alternatively, under the terms of the", + "ordinary General Public License).", + "", + " To apply these terms, attach the following notices to the library. It is", + "safest to attach them to the start of each source file to most effectively", + "convey the exclusion of warranty; and each file should have at least the", + "\"copyright\" line and a pointer to where the full notice is found.", + "", + " ", + " Copyright (C) ", + "", + " This library is free software; you can redistribute it and/or", + " modify it under the terms of the GNU Lesser General Public", + " License as published by the Free Software Foundation; either", + " version 2.1 of the License, or (at your option) any later version.", + "", + " This library is distributed in the hope that it will be useful,", + " but WITHOUT ANY WARRANTY; without even the implied warranty of", + " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU", + " Lesser General Public License for more details.", + "", + " You should have received a copy of the GNU Lesser General Public", + " License along with this library; if not, write to the Free Software", + " Foundation, Inc.,", + "51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA", + "", + "Also add information on how to contact you by electronic and paper mail.", + "", + "You should also get your employer (if you work as a programmer) or your", + "school, if any, to sign a \"copyright disclaimer\" for the library, if", + "necessary. Here is a sample; alter the names:", + "", + " Yoyodyne, Inc., hereby disclaims all copyright interest in the", + " library `Frob' (a library for tweaking knobs) written by James Random Hacker.", + "", + " ,", + "1 April 1990", + " Ty Coon, President of Vice", + "", + "That's all there is to it!" + ] + }, + { + // Added here because the module `parse5` has a dependency to it. + // The module `parse5` is shipped via the `extension-editing` built-in extension. + // The module `parse5` does not want to remove it https://github.com/inikulin/parse5/issues/225 + "name": "@types/node", + "licenseDetail": [ + "This project is licensed under the MIT license.", + "Copyrights are respective of each contributor listed at the beginning of each definition file.", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + ] + }, + { + // We override the license that gets discovered at + // https://github.com/Microsoft/TypeScript/blob/master/LICENSE.txt + // because it does not contain a Copyright statement + "name": "typescript", + "licenseDetail": [ + "Copyright (c) Microsoft Corporation. All rights reserved.", + "", + "Apache License", + "", + "Version 2.0, January 2004", + "", + "http://www.apache.org/licenses/", + "", + "TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION", + "", + "1. Definitions.", + "", + "\"License\" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.", + "", + "\"Licensor\" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.", + "", + "\"Legal Entity\" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, \"control\" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.", + "", + "\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising permissions granted by this License.", + "", + "\"Source\" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.", + "", + "\"Object\" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.", + "", + "\"Work\" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).", + "", + "\"Derivative Works\" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.", + "", + "\"Contribution\" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, \"submitted\" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as \"Not a Contribution.\"", + "", + "\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.", + "", + "2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.", + "", + "3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.", + "", + "4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:", + "", + "You must give any other recipients of the Work or Derivative Works a copy of this License; and", + "", + "You must cause any modified files to carry prominent notices stating that You changed the files; and", + "", + "You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and", + "", + "If the Work includes a \"NOTICE\" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.", + "", + "5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.", + "", + "6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.", + "", + "7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.", + "", + "8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.", + "", + "9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.", + "", + "END OF TERMS AND CONDITIONS" + ] + }, + { + // This module comes in from https://github.com/Microsoft/vscode-node-debug2/blob/master/package-lock.json + "name": "@types/source-map", + "licenseDetail": [ + "This project is licensed under the MIT license.", + "Copyrights are respective of each contributor listed at the beginning of each definition file.", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + ] + }, + { + "name": "tunnel-agent", + "licenseDetail": [ + "Copyright (c) tunnel-agent authors", + "", + "Apache License", + "", + "Version 2.0, January 2004", + "", + "http://www.apache.org/licenses/", + "", + "TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION", + "", + "1. Definitions.", + "", + "\"License\" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.", + "", + "\"Licensor\" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.", + "", + "\"Legal Entity\" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, \"control\" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.", + "", + "\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising permissions granted by this License.", + "", + "\"Source\" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.", + "", + "\"Object\" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.", + "", + "\"Work\" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).", + "", + "\"Derivative Works\" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.", + "", + "\"Contribution\" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, \"submitted\" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as \"Not a Contribution.\"", + "", + "\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.", + "", + "2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.", + "", + "3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.", + "", + "4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:", + "", + "You must give any other recipients of the Work or Derivative Works a copy of this License; and", + "", + "You must cause any modified files to carry prominent notices stating that You changed the files; and", + "", + "You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and", + "", + "If the Work includes a \"NOTICE\" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.", + "", + "5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.", + "", + "6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.", + "", + "7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.", + "", + "8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.", + "", + "9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.", + "", + "END OF TERMS AND CONDITIONS" + ] + }, + { + // Waiting for https://github.com/segmentio/noop-logger/issues/2 + "name": "noop-logger", + "licenseDetail": [ + "This project is licensed under the MIT license.", + "Copyrights are respective of each contributor listed at the beginning of each definition file.", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + ] + }, + { + "name": "xterm-addon-search", + "licenseDetail": [ + "Copyright (c) 2017, The xterm.js authors (https://github.com/xtermjs/xterm.js)", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and associated documentation files (the \"Software\"), to deal", + "in the Software without restriction, including without limitation the rights", + "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell", + "copies of the Software, and to permit persons to whom the Software is", + "furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in", + "all copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", + "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,", + "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN", + "THE SOFTWARE." + ] + }, + { + "name": "xterm-addon-web-links", + "licenseDetail": [ + "Copyright (c) 2017, The xterm.js authors (https://github.com/xtermjs/xterm.js)", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and associated documentation files (the \"Software\"), to deal", + "in the Software without restriction, including without limitation the rights", + "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell", + "copies of the Software, and to permit persons to whom the Software is", + "furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in", + "all copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", + "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,", + "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN", + "THE SOFTWARE." + ] + }, + { + "name": "atob", + "licenseDetail": [ + "The MIT License (MIT)", + "", + "Copyright (c) 2015 AJ ONeal", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and associated documentation files (the \"Software\"), to deal", + "in the Software without restriction, including without limitation the rights", + "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell", + "copies of the Software, and to permit persons to whom the Software is", + "furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in all", + "copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", + "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,", + "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE", + "SOFTWARE." + ] + } +] diff --git a/cgmanifest.json b/cgmanifest.json index f58b3502779..638303702ae 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "chromium", "repositoryUrl": "https://chromium.googlesource.com/chromium/src", - "commitHash": "164c37e3f235134c88e80fac2a182cfba3f07f00" + "commitHash": "c6a08e5368de4352903e702cde750b33239a50ab" } }, "licenseDetail": [ @@ -40,20 +40,7 @@ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ], "isOnlyProductionDependency": true, - "version": "66.0.3359.181" - }, - { - "component": { - "type": "git", - "git": { - "name": "libchromiumcontent", - "repositoryUrl": "https://github.com/electron/libchromiumcontent", - "commitHash": "e38e22ed9f48e6e395f2e9faa93d2d7411f52de4" - } - }, - "isOnlyProductionDependency": true, - "license": "MIT", - "version": "66.0.3359.181" + "version": "69.0.3497.128" }, { "component": { @@ -61,11 +48,11 @@ "git": { "name": "nodejs", "repositoryUrl": "https://github.com/nodejs/node", - "commitHash": "5cbb905c1af7cea2d709932d59827d7c6d03ef4a" + "commitHash": "8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b" } }, "isOnlyProductionDependency": true, - "version": "10.2.0" + "version": "10.11.0" }, { "component": { @@ -73,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "f26dcaeaf39e9b829aa0d4fb5a5cb59c5c314b33" + "commitHash": "36ea114ac0616e469e75ae94e6d53af48925e036" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "3.0.13" + "version": "4.2.7" }, { "component": { @@ -105,6 +92,30 @@ "license": "MIT", "version": "0.14.0" }, + { + "component": { + "type": "git", + "git": { + "name": "vscode-octicons-font", + "repositoryUrl": "https://github.com/Microsoft/vscode-octicons-font", + "commitHash": "415cd5b42ab699b6b46c0bf011ada0a2ae50bfb4" + } + }, + "license": "MIT", + "version": "1.3.1" + }, + { + "component": { + "type": "git", + "git": { + "name": "octicons", + "repositoryUrl": "https://github.com/primer/octicons", + "commitHash": "d120bf97bc9a12fb415f69fedaf31fe58427ca56" + } + }, + "license": "MIT", + "version": "8.3.0" + }, { "component": { "type": "npm", @@ -493,6 +504,19 @@ " defined by the Mozilla Public License, v. 2.0." ], "license": "MPL" + }, + { + "component": { + "type": "git", + "git": { + "name": "ripgrep", + "repositoryUrl": "https://github.com/BurntSushi/ripgrep", + "commitHash": "8a7db1a918e969b85cd933d8ed9fa5285b281ba4" + } + }, + "isOnlyProductionDependency": true, + "license": "MIT", + "version": "0.10.0" } ], "version": 1 diff --git a/extensions/bat/cgmanifest.json b/extensions/bat/cgmanifest.json index 1e21679d7b2..5bc3e285f0c 100644 --- a/extensions/bat/cgmanifest.json +++ b/extensions/bat/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "mmims/language-batchfile", "repositoryUrl": "https://github.com/mmims/language-batchfile", - "commitHash": "4b67596631b4ecd2c89c2ec1b2e08a6623438903" + "commitHash": "95ea8c699f7a8296b15767069868532d52631c46" } }, "license": "MIT", - "version": "0.7.4" + "version": "0.7.5" } ], "version": 1 diff --git a/extensions/bat/package.json b/extensions/bat/package.json index c54d1a4ce5d..00bd84e4ae4 100644 --- a/extensions/bat/package.json +++ b/extensions/bat/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js mmims/language-batchfile grammars/batchfile.cson ./syntaxes/batchfile.tmLanguage.json" diff --git a/extensions/bat/syntaxes/batchfile.tmLanguage.json b/extensions/bat/syntaxes/batchfile.tmLanguage.json index 26ae88f43c5..9eff3c9de2b 100644 --- a/extensions/bat/syntaxes/batchfile.tmLanguage.json +++ b/extensions/bat/syntaxes/batchfile.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/mmims/language-batchfile/commit/4b67596631b4ecd2c89c2ec1b2e08a6623438903", + "version": "https://github.com/mmims/language-batchfile/commit/95ea8c699f7a8296b15767069868532d52631c46", "name": "Batch File", "scopeName": "source.batchfile", "patterns": [ @@ -46,7 +46,7 @@ "commands": { "patterns": [ { - "match": "(?<=^|[\\s@])(?i:adprep|append|arp|assoc|at|atmadm|attrib|auditpol|autochk|autoconv|autofmt|bcdboot|bcdedit|bdehdcfg|bitsadmin|bootcfg|brea|cacls|cd|certreq|certutil|change|chcp|chdir|chglogon|chgport|chgusr|chkdsk|chkntfs|choice|cipher|clip|cls|clscluadmin|cluster|cmd|cmdkey|cmstp|color|comp|compact|convert|copy|cprofile|cscript|csvde|date|dcdiag|dcgpofix|dcpromo|defra|del|dfscmd|dfsdiag|dfsrmig|diantz|dir|dirquota|diskcomp|diskcopy|diskpart|diskperf|diskraid|diskshadow|dispdiag|doin|dnscmd|doskey|driverquery|dsacls|dsadd|dsamain|dsdbutil|dsget|dsmgmt|dsmod|dsmove|dsquery|dsrm|edit|endlocal|eraseesentutl|eventcreate|eventquery|eventtriggers|evntcmd|expand|extract|fc|filescrn|find|findstr|finger|flattemp|fonde|forfiles|format|freedisk|fsutil|ftp|ftype|fveupdate|getmac|gettype|gpfixup|gpresult|gpupdate|graftabl|hashgen|hep|helpctr|hostname|icacls|iisreset|inuse|ipconfig|ipxroute|irftp|ismserv|jetpack|klist|ksetup|ktmutil|ktpass|label|ldifd|ldp|lodctr|logman|logoff|lpq|lpr|macfile|makecab|manage-bde|mapadmin|md|mkdir|mklink|mmc|mode|more|mount|mountvol|move|mqbup|mqsvc|mqtgsvc|msdt|msg|msiexec|msinfo32|mstsc|nbtstat|net computer|net group|net localgroup|net print|net session|net share|net start|net stop|net use|net user|net view|net|netcfg|netdiag|netdom|netsh|netstat|nfsadmin|nfsshare|nfsstat|nlb|nlbmgr|nltest|nslookup|ntackup|ntcmdprompt|ntdsutil|ntfrsutl|openfiles|pagefileconfig|path|pathping|pause|pbadmin|pentnt|perfmon|ping|pnpunatten|pnputil|popd|powercfg|powershell|powershell_ise|print|prncnfg|prndrvr|prnjobs|prnmngr|prnport|prnqctl|prompt|pubprn|pushd|pushprinterconnections|pwlauncher|qappsrv|qprocess|query|quser|qwinsta|rasdial|rcp|rd|rdpsign|regentc|recover|redircmp|redirusr|reg|regini|regsvr32|relog|ren|rename|rendom|repadmin|repair-bde|replace|reset session|rxec|risetup|rmdir|robocopy|route|rpcinfo|rpcping|rsh|runas|rundll32|rwinsta|sc|schtasks|scwcmd|secedit|serverceipoptin|servrmanagercmd|serverweroptin|setspn|setx|sfc|shadow|shift|showmount|shutdown|sort|start|storrept|subst|sxstrace|ysocmgr|systeminfo|takeown|tapicfg|taskkill|tasklist|tcmsetup|telnet|tftp|time|timeout|title|tlntadmn|tpmvscmgr|tpmvscmgr|tacerpt|tracert|tree|tscon|tsdiscon|tsecimp|tskill|tsprof|type|typeperf|tzutil|uddiconfig|umount|unlodctr|ver|verifier|verif|vol|vssadmin|w32tm|waitfor|wbadmin|wdsutil|wecutil|wevtutil|where|whoami|winnt|winnt32|winpop|winrm|winrs|winsat|wlbs|mic|wscript|xcopy)(?=$|\\s)", + "match": "(?<=^|[\\s@])(?i:adprep|append|arp|assoc|at|atmadm|attrib|auditpol|autochk|autoconv|autofmt|bcdboot|bcdedit|bdehdcfg|bitsadmin|bootcfg|brea|cacls|cd|certreq|certutil|change|chcp|chdir|chglogon|chgport|chgusr|chkdsk|chkntfs|choice|cipher|clip|cls|clscluadmin|cluster|cmd|cmdkey|cmstp|color|comp|compact|convert|copy|cprofile|cscript|csvde|date|dcdiag|dcgpofix|dcpromo|defra|del|dfscmd|dfsdiag|dfsrmig|diantz|dir|dirquota|diskcomp|diskcopy|diskpart|diskperf|diskraid|diskshadow|dispdiag|doin|dnscmd|doskey|driverquery|dsacls|dsadd|dsamain|dsdbutil|dsget|dsmgmt|dsmod|dsmove|dsquery|dsrm|edit|endlocal|eraseesentutl|eventcreate|eventquery|eventtriggers|evntcmd|expand|extract|fc|filescrn|find|findstr|finger|flattemp|fonde|forfiles|format|freedisk|fsutil|ftp|ftype|fveupdate|getmac|gettype|gpfixup|gpresult|gpupdate|graftabl|hashgen|hep|helpctr|hostname|icacls|iisreset|inuse|ipconfig|ipxroute|irftp|ismserv|jetpack|klist|ksetup|ktmutil|ktpass|label|ldifd|ldp|lodctr|logman|logoff|lpq|lpr|macfile|makecab|manage-bde|mapadmin|md|mkdir|mklink|mmc|mode|more|mount|mountvol|move|mqbup|mqsvc|mqtgsvc|msdt|msg|msiexec|msinfo32|mstsc|nbtstat|net computer|net group|net localgroup|net print|net session|net share|net start|net stop|net use|net user|net view|net|netcfg|netdiag|netdom|netsh|netstat|nfsadmin|nfsshare|nfsstat|nlb|nlbmgr|nltest|nslookup|ntackup|ntcmdprompt|ntdsutil|ntfrsutl|openfiles|pagefileconfig|path|pathping|pause|pbadmin|pentnt|perfmon|ping|pnpunatten|pnputil|popd|powercfg|powershell|powershell_ise|print|prncnfg|prndrvr|prnjobs|prnmngr|prnport|prnqctl|prompt|pubprn|pushd|pushprinterconnections|pwlauncher|qappsrv|qprocess|query|quser|qwinsta|rasdial|rcp|rd|rdpsign|regentc|recover|redircmp|redirusr|reg|regini|regsvr32|relog|ren|rename|rendom|repadmin|repair-bde|replace|reset session|rxec|risetup|rmdir|robocopy|route|rpcinfo|rpcping|rsh|runas|rundll32|rwinsta|scp|sc|schtasks|scwcmd|secedit|serverceipoptin|servrmanagercmd|serverweroptin|setspn|setx|sfc|shadow|shift|showmount|shutdown|sort|ssh|start|storrept|subst|sxstrace|ysocmgr|systeminfo|takeown|tapicfg|taskkill|tasklist|tcmsetup|telnet|tftp|time|timeout|title|tlntadmn|tpmvscmgr|tpmvscmgr|tacerpt|tracert|tree|tscon|tsdiscon|tsecimp|tskill|tsprof|type|typeperf|tzutil|uddiconfig|umount|unlodctr|ver|verifier|verif|vol|vssadmin|w32tm|waitfor|wbadmin|wdsutil|wecutil|wevtutil|where|whoami|winnt|winnt32|winpop|winrm|winrs|winsat|wlbs|mic|wscript|xcopy)(?=$|\\s)", "name": "keyword.command.batchfile" }, { diff --git a/extensions/clojure/cgmanifest.json b/extensions/clojure/cgmanifest.json index 1a9d69c5633..3a72fefb369 100644 --- a/extensions/clojure/cgmanifest.json +++ b/extensions/clojure/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "atom/language-clojure", "repositoryUrl": "https://github.com/atom/language-clojure", - "commitHash": "ecc790326bc8e14220e4d2d72a392a30876c3219" + "commitHash": "de877502aa4a77ccdc2c7f0c9180436aea3effff" } }, "license": "MIT", - "version": "0.22.6", + "version": "0.22.7", "description": "The file syntaxes/clojure.tmLanguage.json was derived from the Atom package https://github.com/atom/language-clojure which was originally converted from the TextMate bundle https://github.com/mmcgrana/textmate-clojure." } ], diff --git a/extensions/clojure/package.json b/extensions/clojure/package.json index 769b9f46798..3342784348b 100644 --- a/extensions/clojure/package.json +++ b/extensions/clojure/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js atom/language-clojure grammars/clojure.cson ./syntaxes/clojure.tmLanguage.json" diff --git a/extensions/clojure/syntaxes/clojure.tmLanguage.json b/extensions/clojure/syntaxes/clojure.tmLanguage.json index 3d059513af0..29c25edfa24 100644 --- a/extensions/clojure/syntaxes/clojure.tmLanguage.json +++ b/extensions/clojure/syntaxes/clojure.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/atom/language-clojure/commit/ecc790326bc8e14220e4d2d72a392a30876c3219", + "version": "https://github.com/atom/language-clojure/commit/de877502aa4a77ccdc2c7f0c9180436aea3effff", "name": "Clojure", "scopeName": "source.clojure", "patterns": [ @@ -83,7 +83,7 @@ "name": "constant.numeric.ratio.clojure" }, { - "match": "(-?\\d+[rR][0-9a-zA-Z]+)", + "match": "(-?\\d+[rR]\\w+)", "name": "constant.numeric.arbitrary-radix.clojure" }, { @@ -116,17 +116,17 @@ ] }, "keyword": { - "match": "(?<=(\\s|\\(|\\[|\\{)):[a-zA-Z0-9\\#\\.\\-\\_\\:\\+\\=\\>\\<\\/\\!\\?\\*]+(?=(\\s|\\)|\\]|\\}|\\,))", + "match": "(?<=(\\s|\\(|\\[|\\{)):[\\w\\#\\.\\-\\_\\:\\+\\=\\>\\<\\/\\!\\?\\*]+(?=(\\s|\\)|\\]|\\}|\\,))", "name": "constant.keyword.clojure" }, "keyfn": { "patterns": [ { - "match": "(?<=(\\s|\\(|\\[|\\{))(if(-[-a-z\\?]*)?|when(-[-a-z]*)?|for(-[-a-z]*)?|cond|do|let(-[-a-z\\?]*)?|binding|loop|recur|fn|throw[a-z\\-]*|try|catch|finally|([a-z]*case))(?=(\\s|\\)|\\]|\\}))", + "match": "(?<=(\\s|\\(|\\[|\\{))(if(-[-\\p{Ll}\\?]*)?|when(-[-\\p{Ll}]*)?|for(-[-\\p{Ll}]*)?|cond|do|let(-[-\\p{Ll}\\?]*)?|binding|loop|recur|fn|throw[\\p{Ll}\\-]*|try|catch|finally|([\\p{Ll}]*case))(?=(\\s|\\)|\\]|\\}))", "name": "storage.control.clojure" }, { - "match": "(?<=(\\s|\\(|\\[|\\{))(declare-?|(in-)?ns|import|use|require|load|compile|(def[a-z\\-]*))(?=(\\s|\\)|\\]|\\}))", + "match": "(?<=(\\s|\\(|\\[|\\{))(declare-?|(in-)?ns|import|use|require|load|compile|(def[\\p{Ll}\\-]*))(?=(\\s|\\)|\\]|\\}))", "name": "keyword.control.clojure" } ] @@ -309,7 +309,7 @@ "include": "#dynamic-variables" }, { - "match": "([a-zA-Z\\.\\-\\_\\+\\=\\>\\<\\!\\?\\*][\\w\\.\\-\\_\\:\\+\\=\\>\\<\\!\\?\\*\\d]*)", + "match": "([\\p{L}\\.\\-\\_\\+\\=\\>\\<\\!\\?\\*][\\w\\.\\-\\_\\:\\+\\=\\>\\<\\!\\?\\*\\d]*)", "name": "entity.global.clojure" }, { @@ -387,7 +387,7 @@ "namespace-symbol": { "patterns": [ { - "match": "([a-zA-Z\\.\\-\\_\\+\\=\\>\\<\\!\\?\\*][\\w\\.\\-\\_\\:\\+\\=\\>\\<\\!\\?\\*\\d]*)/", + "match": "([\\p{L}\\.\\-\\_\\+\\=\\>\\<\\!\\?\\*][\\w\\.\\-\\_\\:\\+\\=\\>\\<\\!\\?\\*\\d]*)/", "captures": { "1": { "name": "meta.symbol.namespace.clojure" @@ -399,13 +399,13 @@ "symbol": { "patterns": [ { - "match": "([a-zA-Z\\.\\-\\_\\+\\=\\>\\<\\!\\?\\*][\\w\\.\\-\\_\\:\\+\\=\\>\\<\\!\\?\\*\\d]*)", + "match": "([\\p{L}\\.\\-\\_\\+\\=\\>\\<\\!\\?\\*][\\w\\.\\-\\_\\:\\+\\=\\>\\<\\!\\?\\*\\d]*)", "name": "meta.symbol.clojure" } ] }, "var": { - "match": "(?<=(\\s|\\(|\\[|\\{)\\#)'[a-zA-Z0-9\\.\\-\\_\\:\\+\\=\\>\\<\\/\\!\\?\\*]+(?=(\\s|\\)|\\]|\\}))", + "match": "(?<=(\\s|\\(|\\[|\\{)\\#)'[\\w\\.\\-\\_\\:\\+\\=\\>\\<\\/\\!\\?\\*]+(?=(\\s|\\)|\\]|\\}))", "name": "meta.var.clojure" }, "vector": { diff --git a/extensions/coffeescript/cgmanifest.json b/extensions/coffeescript/cgmanifest.json index 3731fb9e3ff..3c792173e6e 100644 --- a/extensions/coffeescript/cgmanifest.json +++ b/extensions/coffeescript/cgmanifest.json @@ -6,12 +6,12 @@ "git": { "name": "atom/language-coffee-script", "repositoryUrl": "https://github.com/atom/language-coffee-script", - "commitHash": "a0da2a73ad817e2fc13c2ef8fcd2624017c39610" + "commitHash": "0f6db9143663e18b1ad00667820f46747dba495e" } }, "license": "MIT", "description": "The file syntaxes/coffeescript.tmLanguage.json was derived from the Atom package https://github.com/atom/language-coffee-script which was originally converted from the TextMate bundle https://github.com/jashkenas/coffee-script-tmbundle.", - "version": "0.49.2" + "version": "0.49.3" } ], "version": 1 diff --git a/extensions/coffeescript/package.json b/extensions/coffeescript/package.json index 2758bcdc50b..df5f8ff7c1f 100644 --- a/extensions/coffeescript/package.json +++ b/extensions/coffeescript/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js atom/language-coffee-script grammars/coffeescript.cson ./syntaxes/coffeescript.tmLanguage.json" @@ -11,7 +12,7 @@ "contributes": { "languages": [{ "id": "coffeescript", - "extensions": [ ".coffee", ".cson" ], + "extensions": [ ".coffee", ".cson", ".iced" ], "aliases": [ "CoffeeScript", "coffeescript", "coffee" ], "configuration": "./language-configuration.json" }], diff --git a/extensions/coffeescript/syntaxes/coffeescript.tmLanguage.json b/extensions/coffeescript/syntaxes/coffeescript.tmLanguage.json index 5fcff295c61..708856898bc 100644 --- a/extensions/coffeescript/syntaxes/coffeescript.tmLanguage.json +++ b/extensions/coffeescript/syntaxes/coffeescript.tmLanguage.json @@ -4,10 +4,13 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/atom/language-coffee-script/commit/a0da2a73ad817e2fc13c2ef8fcd2624017c39610", + "version": "https://github.com/atom/language-coffee-script/commit/0f6db9143663e18b1ad00667820f46747dba495e", "name": "CoffeeScript", "scopeName": "source.coffee", "patterns": [ + { + "include": "#jsx" + }, { "match": "(new)\\s+(?:(?:(class)\\s+(\\w+(?:\\.\\w*)*)?)|(\\w+(?:\\.\\w*)*))", "name": "meta.class.instance.constructor.coffee", @@ -1213,6 +1216,101 @@ "include": "#embedded_comment" } ] + }, + "jsx": { + "patterns": [ + { + "include": "#jsx-tag" + }, + { + "include": "#jsx-end-tag" + } + ] + }, + "jsx-expression": { + "begin": "{", + "beginCaptures": { + "0": { + "name": "meta.brace.curly.coffee" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "meta.brace.curly.coffee" + } + }, + "patterns": [ + { + "include": "#double_quoted_string" + }, + { + "include": "$self" + } + ] + }, + "jsx-attribute": { + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.coffee" + }, + "2": { + "name": "keyword.operator.assignment.coffee" + } + }, + "match": "(?:^|\\s+)([-\\w.]+)\\s*(=)" + }, + { + "include": "#double_quoted_string" + }, + { + "include": "#single_quoted_string" + }, + { + "include": "#jsx-expression" + } + ] + }, + "jsx-tag": { + "patterns": [ + { + "begin": "(<)([-\\w\\.]+)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.coffee" + }, + "2": { + "name": "entity.name.tag.coffee" + } + }, + "end": "(/?>)", + "name": "meta.tag.coffee", + "patterns": [ + { + "include": "#jsx-attribute" + } + ] + } + ] + }, + "jsx-end-tag": { + "patterns": [ + { + "begin": "()", + "name": "meta.tag.coffee" + } + ] } } } \ No newline at end of file diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json index 46f4eba3a95..e555d61457e 100644 --- a/extensions/configuration-editing/package.json +++ b/extensions/configuration-editing/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "^1.0.0" }, @@ -57,6 +58,10 @@ "fileMatch": "%APP_SETTINGS_HOME%/settings.json", "url": "vscode://schemas/settings/user" }, + { + "fileMatch": "%MACHINE_SETTINGS_HOME%/settings.json", + "url": "vscode://schemas/settings/machine" + }, { "fileMatch": "%APP_WORKSPACES_HOME%/*/workspace.json", "url": "vscode://schemas/workspaceConfig" @@ -92,10 +97,18 @@ { "fileMatch": "/.vscode/extensions.json", "url": "vscode://schemas/extensions" + }, + { + "fileMatch": "/.devcontainer/devcontainer.json", + "url": "./schemas/devContainer.schema.json" + }, + { + "fileMatch": "/.devcontainer.json", + "url": "./schemas/devContainer.schema.json" } ] }, "devDependencies": { - "@types/node": "^8.10.25" + "@types/node": "^10.14.8" } } diff --git a/extensions/configuration-editing/schemas/devContainer.schema.json b/extensions/configuration-editing/schemas/devContainer.schema.json new file mode 100644 index 00000000000..55950a9021e --- /dev/null +++ b/extensions/configuration-editing/schemas/devContainer.schema.json @@ -0,0 +1,181 @@ +{ + "$schema": "http://json-schema.org/schema#", + "description": "Defines a dev container", + "allowComments": true, + "type": "object", + "definitions": { + "devContainerCommon": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "A name to show for the workspace folder." + }, + "extensions": { + "type": "array", + "description": "An array of extensions that should be installed into the container.", + "items": { + "type": "string" + } + }, + "settings": { + "$ref": "vscode://schemas/settings/machine", + "description": "Machine specific settings that should be copied into the container." + }, + "postCreateCommand": { + "type": [ + "string", + "array" + ], + "description": "A command to run after creating the container. If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell.", + "items": { + "type": "string" + } + }, + "devPort": { + "type": "integer", + "description": "The port VS Code can use to connect to its backend." + } + } + }, + "nonComposeBase": { + "type": "object", + "properties": { + "appPort": { + "type": [ + "integer", + "string", + "array" + ], + "description": "Application ports that are exposed by the container. This can be a single port or an array of ports. Each port can be a number or a string. A number is mapped to the same port on the host. A string is passed to Docker unchanged and can be used to map ports differently, e.g. \"8000:8010\".", + "items": { + "type": [ + "integer", + "string" + ] + } + }, + "runArgs": { + "type": "array", + "description": "The arguments required when starting in the container.", + "items": { + "type": "string" + } + }, + "shutdownAction": { + "type": "string", + "enum": [ + "none", + "stopContainer" + ], + "description": "Action to take when VS Code is shutting down. The default is to stop the container." + }, + "overrideCommand": { + "type": "boolean", + "description": "Whether to overwrite the command specified in the image. The default is true." + }, + "workspaceFolder": { + "type": "string", + "description": "The path of the workspace folder inside the container." + }, + "workspaceMount": { + "type": "string", + "description": "The --mount parameter for docker run. The default is to mount the project folder at /workspaces/$project." + } + } + }, + "dockerFileContainer": { + "type": "object", + "properties": { + "dockerFile": { + "type": "string", + "description": "The location of the Dockerfile that defines the contents of the container. The path is relative to the folder containing the `devcontainer.json` file." + }, + "context": { + "type": "string", + "description": "The location of the context folder for building the Docker image. The path is relative to the folder containing the `devcontainer.json` file." + } + }, + "required": [ + "dockerFile" + ] + }, + "imageContainer": { + "type": "object", + "properties": { + "image": { + "type": "string", + "description": "The docker image that will be used to create the container." + } + }, + "required": [ + "image" + ] + }, + "composeContainer": { + "type": "object", + "properties": { + "dockerComposeFile": { + "type": [ + "string", + "array" + ], + "description": "The name of the docker-compose file(s) used to start the services.", + "items": { + "type": "string" + } + }, + "service": { + "type": "string", + "description": "The service you want to work on." + }, + "workspaceFolder": { + "type": "string", + "description": "The path of the workspace folder inside the container." + }, + "shutdownAction": { + "type": "string", + "enum": [ + "none", + "stopCompose" + ], + "description": "Action to take when VS Code is shutting down. The default is to stop the containers." + } + }, + "required": [ + "dockerComposeFile", + "service", + "workspaceFolder" + ] + } + }, + "allOf": [ + { + "oneOf": [ + { + "allOf": [ + { + "oneOf": [ + { + "$ref": "#/definitions/dockerFileContainer" + }, + { + "$ref": "#/definitions/imageContainer" + } + ] + }, + { + "$ref": "#/definitions/nonComposeBase" + } + ] + }, + { + "$ref": "#/definitions/composeContainer" + } + ] + }, + { + "$ref": "#/definitions/devContainerCommon" + } + ] +} \ No newline at end of file diff --git a/extensions/configuration-editing/src/extension.ts b/extensions/configuration-editing/src/extension.ts index b0a083e7e9e..aff533d86d9 100644 --- a/extensions/configuration-editing/src/extension.ts +++ b/extensions/configuration-editing/src/extension.ts @@ -3,12 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vscode-nls'; -const localize = nls.loadMessageBundle(); -import * as vscode from 'vscode'; -import { getLocation, visit, parse, ParseErrorCode } from 'jsonc-parser'; +import { getLocation, parse, visit } from 'jsonc-parser'; import * as path from 'path'; +import * as vscode from 'vscode'; +import * as nls from 'vscode-nls'; import { SettingsDocument } from './settingsDocumentHelper'; +const localize = nls.loadMessageBundle(); const fadedDecoration = vscode.window.createTextEditorDecorationType({ light: { @@ -22,9 +22,6 @@ const fadedDecoration = vscode.window.createTextEditorDecorationType({ let pendingLaunchJsonDecoration: NodeJS.Timer; export function activate(context: vscode.ExtensionContext): void { - //keybindings.json command-suggestions - context.subscriptions.push(registerKeybindingsCompletions()); - //settings.json suggestions context.subscriptions.push(registerSettingsCompletions()); @@ -48,67 +45,6 @@ export function activate(context: vscode.ExtensionContext): void { } }, null, context.subscriptions)); updateLaunchJsonDecorations(vscode.window.activeTextEditor); - - context.subscriptions.push(vscode.workspace.onWillSaveTextDocument(e => { - if (!e.document.fileName.endsWith('/settings.json')) { - return; - } - - autoFixSettingsJSON(e); - })); -} - -function autoFixSettingsJSON(willSaveEvent: vscode.TextDocumentWillSaveEvent): void { - const document = willSaveEvent.document; - const text = document.getText(); - const edit = new vscode.WorkspaceEdit(); - - let lastEndOfSomething = -1; - visit(text, { - onArrayEnd(offset: number, length: number): void { - lastEndOfSomething = offset + length; - }, - - onLiteralValue(_value: any, offset: number, length: number): void { - lastEndOfSomething = offset + length; - }, - - onObjectEnd(offset: number, length: number): void { - lastEndOfSomething = offset + length; - }, - - onError(error: ParseErrorCode, _offset: number, _length: number): void { - if (error === ParseErrorCode.CommaExpected && lastEndOfSomething > -1) { - const fixPosition = document.positionAt(lastEndOfSomething); - - // Don't insert a comma immediately before a : or ' :' - const colonRange = document.getWordRangeAtPosition(fixPosition, / *:/); - if (!colonRange) { - edit.insert(document.uri, fixPosition, ','); - } - } - } - }); - - willSaveEvent.waitUntil( - vscode.workspace.applyEdit(edit)); -} - -function registerKeybindingsCompletions(): vscode.Disposable { - const commands = vscode.commands.getCommands(true); - - return vscode.languages.registerCompletionItemProvider({ pattern: '**/keybindings.json' }, { - - provideCompletionItems(document, position, _token) { - const location = getLocation(document.getText(), document.offsetAt(position)); - if (location.path[1] === 'command') { - - const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position); - return commands.then(ids => ids.map(id => newSimpleCompletionItem(JSON.stringify(id), range))); - } - return undefined; - } - }); } function registerSettingsCompletions(): vscode.Disposable { @@ -127,11 +63,20 @@ function registerVariableCompletions(pattern: string): vscode.Disposable { const indexOf$ = document.lineAt(position.line).text.indexOf('$'); const startPosition = indexOf$ >= 0 ? new vscode.Position(position.line, indexOf$) : position; - return [{ label: 'workspaceFolder', detail: localize('workspaceFolder', "The path of the folder opened in VS Code") }, { label: 'workspaceFolderBasename', detail: localize('workspaceFolderBasename', "The name of the folder opened in VS Code without any slashes (/)") }, - { label: 'relativeFile', detail: localize('relativeFile', "The current opened file relative to ${workspaceFolder}") }, { label: 'file', detail: localize('file', "The current opened file") }, { label: 'cwd', detail: localize('cwd', "The task runner's current working directory on startup") }, - { label: 'lineNumber', detail: localize('lineNumber', "The current selected line number in the active file") }, { label: 'selectedText', detail: localize('selectedText', "The current selected text in the active file") }, - { label: 'fileDirname', detail: localize('fileDirname', "The current opened file's dirname") }, { label: 'fileExtname', detail: localize('fileExtname', "The current opened file's extension") }, { label: 'fileBasename', detail: localize('fileBasename', "The current opened file's basename") }, - { label: 'fileBasenameNoExtension', detail: localize('fileBasenameNoExtension', "The current opened file's basename with no file extension") }].map(variable => ({ + return [ + { label: 'workspaceFolder', detail: localize('workspaceFolder', "The path of the folder opened in VS Code") }, + { label: 'workspaceFolderBasename', detail: localize('workspaceFolderBasename', "The name of the folder opened in VS Code without any slashes (/)") }, + { label: 'relativeFile', detail: localize('relativeFile', "The current opened file relative to ${workspaceFolder}") }, + { label: 'relativeFileDirname', detail: localize('relativeFileDirname', "The current opened file's dirname relative to ${workspaceFolder}") }, + { label: 'file', detail: localize('file', "The current opened file") }, + { label: 'cwd', detail: localize('cwd', "The task runner's current working directory on startup") }, + { label: 'lineNumber', detail: localize('lineNumber', "The current selected line number in the active file") }, + { label: 'selectedText', detail: localize('selectedText', "The current selected text in the active file") }, + { label: 'fileDirname', detail: localize('fileDirname', "The current opened file's dirname") }, + { label: 'fileExtname', detail: localize('fileExtname', "The current opened file's extension") }, + { label: 'fileBasename', detail: localize('fileBasename', "The current opened file's basename") }, + { label: 'fileBasenameNoExtension', detail: localize('fileBasenameNoExtension', "The current opened file's basename with no file extension") } + ].map(variable => ({ label: '${' + variable.label + '}', range: new vscode.Range(startPosition, position), detail: variable.detail @@ -207,16 +152,6 @@ function provideInstalledExtensionProposals(extensionsContent: IExtensionsConten return undefined; } -function newSimpleCompletionItem(label: string, range: vscode.Range, description?: string, insertText?: string): vscode.CompletionItem { - const item = new vscode.CompletionItem(label); - item.kind = vscode.CompletionItemKind.Value; - item.detail = description; - item.insertText = insertText || label; - item.range = range; - - return item; -} - function updateLaunchJsonDecorations(editor: vscode.TextEditor | undefined): void { if (!editor || path.basename(editor.document.fileName) !== 'launch.json') { return; diff --git a/extensions/configuration-editing/src/settingsDocumentHelper.ts b/extensions/configuration-editing/src/settingsDocumentHelper.ts index e6b137809ff..d4ac414897d 100644 --- a/extensions/configuration-editing/src/settingsDocumentHelper.ts +++ b/extensions/configuration-editing/src/settingsDocumentHelper.ts @@ -44,8 +44,11 @@ export class SettingsDocument { const completions: vscode.CompletionItem[] = []; completions.push(this.newSimpleCompletionItem('${activeEditorShort}', range, localize('activeEditorShort', "the file name (e.g. myFile.txt)"))); - completions.push(this.newSimpleCompletionItem('${activeEditorMedium}', range, localize('activeEditorMedium', "the path of the file relative to the workspace folder (e.g. myFolder/myFile.txt)"))); - completions.push(this.newSimpleCompletionItem('${activeEditorLong}', range, localize('activeEditorLong', "the full path of the file (e.g. /Users/Development/myProject/myFolder/myFile.txt)"))); + completions.push(this.newSimpleCompletionItem('${activeEditorMedium}', range, localize('activeEditorMedium', "the path of the file relative to the workspace folder (e.g. myFolder/myFileFolder/myFile.txt)"))); + completions.push(this.newSimpleCompletionItem('${activeEditorLong}', range, localize('activeEditorLong', "the full path of the file (e.g. /Users/Development/myFolder/myFileFolder/myFile.txt)"))); + completions.push(this.newSimpleCompletionItem('${activeFolderShort}', range, localize('activeFolderShort', "the name of the folder the file is contained in (e.g. myFileFolder)"))); + completions.push(this.newSimpleCompletionItem('${activeFolderMedium}', range, localize('activeFolderMedium', "the path of the folder the file is contained in, relative to the workspace folder (e.g. myFolder/myFileFolder)"))); + completions.push(this.newSimpleCompletionItem('${activeFolderLong}', range, localize('activeFolderLong', "the full path of the folder the file is contained in (e.g. /Users/Development/myFolder/myFileFolder)"))); completions.push(this.newSimpleCompletionItem('${rootName}', range, localize('rootName', "name of the workspace (e.g. myFolder or myWorkspace)"))); completions.push(this.newSimpleCompletionItem('${rootPath}', range, localize('rootPath', "file path of the workspace (e.g. /Users/Development/myWorkspace)"))); completions.push(this.newSimpleCompletionItem('${folderName}', range, localize('folderName', "name of the workspace folder the file is contained in (e.g. myFolder)"))); diff --git a/extensions/configuration-editing/yarn.lock b/extensions/configuration-editing/yarn.lock index 752f2a3a6f9..ce653f097a9 100644 --- a/extensions/configuration-editing/yarn.lock +++ b/extensions/configuration-editing/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== jsonc-parser@2.0.2: version "2.0.2" diff --git a/extensions/cpp/build/update-grammars.js b/extensions/cpp/build/update-grammars.js index f02f51ca2cc..29761cdaf95 100644 --- a/extensions/cpp/build/update-grammars.js +++ b/extensions/cpp/build/update-grammars.js @@ -6,8 +6,8 @@ var updateGrammar = require('../../../build/npm/update-grammar'); -updateGrammar.update('atom/language-c', 'grammars/c.cson', './syntaxes/c.tmLanguage.json'); -updateGrammar.update('atom/language-c', 'grammars/c%2B%2B.cson', './syntaxes/cpp.tmLanguage.json'); +updateGrammar.update('jeff-hykin/cpp-textmate-grammar', '/syntaxes/c.tmLanguage.json', './syntaxes/c.tmLanguage.json', undefined, 'master', 'source/languages/cpp'); +updateGrammar.update('jeff-hykin/cpp-textmate-grammar', '/syntaxes/cpp.tmLanguage.json', './syntaxes/cpp.tmLanguage.json', undefined, 'master', 'source/languages/cpp'); // `source.c.platform` which is still included by other grammars updateGrammar.update('textmate/c.tmbundle', 'Syntaxes/Platform.tmLanguage', './syntaxes/platform.tmLanguage.json'); diff --git a/extensions/cpp/cgmanifest.json b/extensions/cpp/cgmanifest.json index e6666933f61..768ca68ecbc 100644 --- a/extensions/cpp/cgmanifest.json +++ b/extensions/cpp/cgmanifest.json @@ -4,14 +4,14 @@ "component": { "type": "git", "git": { - "name": "atom/language-c", - "repositoryUrl": "https://github.com/atom/language-c", - "commitHash": "9c0c5f202741a5647025db8d5df5fefba47b036c" + "name": "jeff-hykin/cpp-textmate-grammar", + "repositoryUrl": "https://github.com/jeff-hykin/cpp-textmate-grammar", + "commitHash": "cbd71f90cd9be0f99ddc9b0f65cec62fc3ada6d1" } }, "license": "MIT", - "version": "0.58.1", - "description": "The files syntaxes/c.json and syntaxes/c++.json were derived from the Atom package https://atom.io/packages/language-c which was originally converted from the C TextMate bundle https://github.com/textmate/c.tmbundle." + "version": "1.12.21", + "description": "The files syntaxes/c.json and syntaxes/c++.json were derived from https://github.com/atom/language-c which was originally converted from the C TextMate bundle https://github.com/textmate/c.tmbundle." }, { "component": { diff --git a/extensions/cpp/language-configuration.json b/extensions/cpp/language-configuration.json index e50df32dd11..d430c4d1518 100644 --- a/extensions/cpp/language-configuration.json +++ b/extensions/cpp/language-configuration.json @@ -29,4 +29,4 @@ "end": "^\\s*#pragma\\s+endregion\\b" } } -} \ No newline at end of file +} diff --git a/extensions/cpp/package.json b/extensions/cpp/package.json index ff7ddb1023d..6d8ae8b81df 100644 --- a/extensions/cpp/package.json +++ b/extensions/cpp/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ./build/update-grammars.js" @@ -17,7 +18,7 @@ }, { "id": "cpp", - "extensions": [ ".cpp", ".cc", ".cxx", ".hpp", ".hh", ".hxx", ".h", ".ino", ".inl", ".ipp" ], + "extensions": [ ".cpp", ".cc", ".cxx", ".hpp", ".hh", ".hxx", ".h", ".i", ".ino", ".inl", ".ipp", ".hpp.in", ".h.in" ], "aliases": [ "C++", "Cpp", "cpp"], "configuration": "./language-configuration.json" }], @@ -44,4 +45,4 @@ "path": "./snippets/cpp.json" }] } -} \ No newline at end of file +} diff --git a/extensions/cpp/syntaxes/c.tmLanguage.json b/extensions/cpp/syntaxes/c.tmLanguage.json index bcd5470a64c..1a95c101984 100644 --- a/extensions/cpp/syntaxes/c.tmLanguage.json +++ b/extensions/cpp/syntaxes/c.tmLanguage.json @@ -1,10 +1,10 @@ { "information_for_contributors": [ - "This file has been converted from https://github.com/atom/language-c/blob/master/grammars/c.cson", + "This file has been converted from https://github.com/jeff-hykin/cpp-textmate-grammar/blob/master//syntaxes/c.tmLanguage.json", "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/atom/language-c/commit/9c0c5f202741a5647025db8d5df5fefba47b036c", + "version": "https://github.com/jeff-hykin/cpp-textmate-grammar/commit/5209e7f9df7661db6f163753141eeb3de6fb02b3", "name": "C", "scopeName": "source.c", "patterns": [ @@ -17,16 +17,26 @@ { "include": "#preprocessor-rule-conditional" }, + { + "include": "#predefined_macros" + }, { "include": "#comments" }, { - "match": "\\b(break|case|continue|default|do|else|for|goto|if|_Pragma|return|switch|while)\\b", + "include": "#switch_statement" + }, + { + "match": "\\b(break|continue|do|else|for|goto|if|_Pragma|return|while)\\b", "name": "keyword.control.c" }, { "include": "#storage_types" }, + { + "match": "typedef", + "name": "keyword.other.typedef.c" + }, { "match": "\\b(const|extern|register|restrict|static|volatile|inline)\\b", "name": "storage.modifier.c" @@ -57,32 +67,71 @@ "include": "#strings" }, { - "begin": "(?x)\n^\\s* ((\\#)\\s*define) \\s+ # define\n((?[a-zA-Z_$][\\w$]*)) # macro name\n(?:\n (\\()\n (\n \\s* \\g \\s* # first argument\n ((,) \\s* \\g \\s*)* # additional arguments\n (?:\\.\\.\\.)? # varargs ellipsis?\n )\n (\\))\n)?", + "name": "meta.preprocessor.macro.c", + "begin": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((#)\\s*define\\b)\\s+((?=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", - "end": "(?<=\\))(?!\\w)", "name": "meta.function.c", + "begin": "(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/))", "captures": { + "1": { + "name": "comment.block.c punctuation.definition.comment.begin.c" + }, + "2": { + "name": "comment.block.c" + }, + "3": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.c punctuation.definition.comment.end.c" + }, + { + "match": "\\*", + "name": "comment.block.c" + } + ] + } + } + }, + "default_statement": { + "name": "meta.conditional.case.c", + "begin": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?|\\?\\?>)|(?=[;>\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.switch.c", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.switch.c" + } + }, + "patterns": [ + { + "include": "#switch_conditional_parentheses" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.body.switch.c", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.switch.c" + } + }, + "patterns": [ + { + "include": "#default_statement" + }, + { + "include": "#case_statement" + }, + { + "include": "$self" + }, + { + "include": "#block_innards" + } + ] + }, + { + "name": "meta.tail.switch.c", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "switch_conditional_parentheses": { + "name": "meta.conditional.switch.c", + "begin": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.c punctuation.definition.comment.begin.c" + }, + "3": { + "name": "comment.block.c" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.c punctuation.definition.comment.end.c" + }, + { + "match": "\\*", + "name": "comment.block.c" + } + ] + }, + "5": { + "name": "punctuation.section.parens.begin.bracket.round.conditional.switch.c" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.conditional.switch.c" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + }, + { + "include": "#c_conditional_context" + } + ] + }, + "static_assert": { + "begin": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.c punctuation.definition.comment.begin.c" + }, + "3": { + "name": "comment.block.c" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.c punctuation.definition.comment.end.c" + }, + { + "match": "\\*", + "name": "comment.block.c" + } + ] + }, + "5": { + "name": "keyword.other.static_assert.c" + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.c punctuation.definition.comment.begin.c" + }, + "8": { + "name": "comment.block.c" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.c punctuation.definition.comment.end.c" + }, + { + "match": "\\*", + "name": "comment.block.c" + } + ] + }, + "10": { + "name": "punctuation.section.arguments.begin.bracket.round.static_assert.c" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.static_assert.c" + } + }, + "patterns": [ + { + "name": "meta.static_assert.message.c", + "begin": "(,)\\s*(?=(?:L|u8|u|U\\s*\\\")?)", + "beginCaptures": { + "1": { + "name": "punctuation.separator.delimiter.comma.c" + } + }, + "end": "(?=\\))", + "patterns": [ + { + "include": "#string_context" + }, + { + "include": "#string_context_c" + } + ] + }, + { + "include": "#evaluation_context" + } + ] + }, + "backslash_escapes": { + "match": "(?x)\\\\ (\n\\\\\t\t\t |\n[abefnprtv'\"?] |\n[0-3]\\d{,2}\t |\n[4-7]\\d?\t\t|\nx[a-fA-F0-9]{,2} |\nu[a-fA-F0-9]{,4} |\nU[a-fA-F0-9]{,8} )", + "name": "constant.character.escape.c" + }, + "c_conditional_context": { + "patterns": [ + { + "include": "$self" + }, + { + "include": "#block_innards" + } + ] + }, + "evalutation_context": { + "patterns": [ + { + "include": "#function-call-innards" + }, + { + "include": "$base" + } + ] + }, + "member_access": { + "match": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))((?:[a-zA-Z_]\\w*\\s*(?:(?:(?:\\.\\*|\\.))|(?:(?:->\\*|->)))\\s*)*)\\s*(\\b(?!(?:void|char|short|int|signed|unsigned|long|float|double|bool|_Bool|_Complex|_Imaginary|u_char|u_short|u_int|u_long|ushort|uint|u_quad_t|quad_t|qaddr_t|caddr_t|daddr_t|div_t|dev_t|fixpt_t|blkcnt_t|blksize_t|gid_t|in_addr_t|in_port_t|ino_t|key_t|mode_t|nlink_t|id_t|pid_t|off_t|segsz_t|swblk_t|uid_t|id_t|clock_t|size_t|ssize_t|time_t|useconds_t|suseconds_t|pthread_attr_t|pthread_cond_t|pthread_condattr_t|pthread_mutex_t|pthread_mutexattr_t|pthread_once_t|pthread_rwlock_t|pthread_rwlockattr_t|pthread_t|pthread_key_t|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|int_least8_t|int_least16_t|int_least32_t|int_least64_t|uint_least8_t|uint_least16_t|uint_least32_t|uint_least64_t|int_fast8_t|int_fast16_t|int_fast32_t|int_fast64_t|uint_fast8_t|uint_fast16_t|uint_fast32_t|uint_fast64_t|intptr_t|uintptr_t|intmax_t|intmax_t|uintmax_t|uintmax_t|memory_order|atomic_bool|atomic_char|atomic_schar|atomic_uchar|atomic_short|atomic_ushort|atomic_int|atomic_uint|atomic_long|atomic_ulong|atomic_llong|atomic_ullong|atomic_char16_t|atomic_char32_t|atomic_wchar_t|atomic_int_least8_t|atomic_uint_least8_t|atomic_int_least16_t|atomic_uint_least16_t|atomic_int_least32_t|atomic_uint_least32_t|atomic_int_least64_t|atomic_uint_least64_t|atomic_int_fast8_t|atomic_uint_fast8_t|atomic_int_fast16_t|atomic_uint_fast16_t|atomic_int_fast32_t|atomic_uint_fast32_t|atomic_int_fast64_t|atomic_uint_fast64_t|atomic_intptr_t|atomic_uintptr_t|atomic_size_t|atomic_ptrdiff_t|atomic_intmax_t|atomic_uintmax_t)\\b)[a-zA-Z_]\\w*\\b(?!\\())", + "captures": { + "1": { + "name": "variable.other.object.access.c" + }, "2": { "name": "punctuation.separator.dot-access.c" }, @@ -311,10 +797,1413 @@ "name": "punctuation.separator.pointer-access.c" }, "4": { + "patterns": [ + { + "include": "#member_access" + }, + { + "include": "#method_access" + }, + { + "match": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))", + "captures": { + "1": { + "name": "variable.other.object.access.c" + }, + "2": { + "name": "punctuation.separator.dot-access.c" + }, + "3": { + "name": "punctuation.separator.pointer-access.c" + } + } + } + ] + }, + "5": { "name": "variable.other.member.c" } + } + }, + "method_access": { + "contentName": "meta.function-call.member.c", + "begin": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))((?:[a-zA-Z_]\\w*\\s*(?:(?:(?:\\.\\*|\\.))|(?:(?:->\\*|->)))\\s*)*)\\s*([a-zA-Z_]\\w*)(\\()", + "beginCaptures": { + "1": { + "name": "variable.other.object.access.c" + }, + "2": { + "name": "punctuation.separator.dot-access.c" + }, + "3": { + "name": "punctuation.separator.pointer-access.c" + }, + "4": { + "patterns": [ + { + "include": "#member_access" + }, + { + "include": "#method_access" + }, + { + "match": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))", + "captures": { + "1": { + "name": "variable.other.object.access.c" + }, + "2": { + "name": "punctuation.separator.dot-access.c" + }, + "3": { + "name": "punctuation.separator.pointer-access.c" + } + } + } + ] + }, + "5": { + "name": "entity.name.function.member.c" + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.function.member.c" + } }, - "match": "((\\.)|(->))\\s*(([a-zA-Z_][a-zA-Z_0-9]*)\\b(?!\\s*\\())?" + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.function.member.c" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + "predefined_macros": { + "patterns": [ + { + "match": "\\b__cplusplus\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__cplusplus.c" + }, + { + "match": "\\b__DATE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__DATE__.c" + }, + { + "match": "\\b__FILE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FILE__.c" + }, + { + "match": "\\b__LINE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__LINE__.c" + }, + { + "match": "\\b__STDC__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__STDC__.c" + }, + { + "match": "\\b__STDC_HOSTED__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__STDC_HOSTED__.c" + }, + { + "match": "\\b__STDC_NO_COMPLEX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__STDC_NO_COMPLEX__.c" + }, + { + "match": "\\b__STDC_VERSION__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__STDC_VERSION__.c" + }, + { + "match": "\\b__STDCPP_THREADS__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__STDCPP_THREADS__.c" + }, + { + "match": "\\b__TIME__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__TIME__.c" + }, + { + "match": "\\bNDEBUG\\b", + "name": "entity.name.other.preprocessor.macro.predefined.NDEBUG.c" + }, + { + "match": "\\b__OBJC__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__OBJC__.c" + }, + { + "match": "\\b__ASSEMBLER__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__ASSEMBLER__.c" + }, + { + "match": "\\b__ATOM__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__ATOM__.c" + }, + { + "match": "\\b__AVX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__AVX__.c" + }, + { + "match": "\\b__AVX2__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__AVX2__.c" + }, + { + "match": "\\b_CHAR_UNSIGNED\\b", + "name": "entity.name.other.preprocessor.macro.predefined._CHAR_UNSIGNED.c" + }, + { + "match": "\\b__CLR_VER\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__CLR_VER.c" + }, + { + "match": "\\b_CONTROL_FLOW_GUARD\\b", + "name": "entity.name.other.preprocessor.macro.predefined._CONTROL_FLOW_GUARD.c" + }, + { + "match": "\\b__COUNTER__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__COUNTER__.c" + }, + { + "match": "\\b__cplusplus_cli\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__cplusplus_cli.c" + }, + { + "match": "\\b__cplusplus_winrt\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__cplusplus_winrt.c" + }, + { + "match": "\\b_CPPRTTI\\b", + "name": "entity.name.other.preprocessor.macro.predefined._CPPRTTI.c" + }, + { + "match": "\\b_CPPUNWIND\\b", + "name": "entity.name.other.preprocessor.macro.predefined._CPPUNWIND.c" + }, + { + "match": "\\b_DEBUG\\b", + "name": "entity.name.other.preprocessor.macro.predefined._DEBUG.c" + }, + { + "match": "\\b_DLL\\b", + "name": "entity.name.other.preprocessor.macro.predefined._DLL.c" + }, + { + "match": "\\b__FUNCDNAME__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FUNCDNAME__.c" + }, + { + "match": "\\b__FUNCSIG__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FUNCSIG__.c" + }, + { + "match": "\\b__FUNCTION__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FUNCTION__.c" + }, + { + "match": "\\b_INTEGRAL_MAX_BITS\\b", + "name": "entity.name.other.preprocessor.macro.predefined._INTEGRAL_MAX_BITS.c" + }, + { + "match": "\\b__INTELLISENSE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INTELLISENSE__.c" + }, + { + "match": "\\b_ISO_VOLATILE\\b", + "name": "entity.name.other.preprocessor.macro.predefined._ISO_VOLATILE.c" + }, + { + "match": "\\b_KERNEL_MODE\\b", + "name": "entity.name.other.preprocessor.macro.predefined._KERNEL_MODE.c" + }, + { + "match": "\\b_M_AMD64\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_AMD64.c" + }, + { + "match": "\\b_M_ARM\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_ARM.c" + }, + { + "match": "\\b_M_ARM_ARMV7VE\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_ARM_ARMV7VE.c" + }, + { + "match": "\\b_M_ARM_FP\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_ARM_FP.c" + }, + { + "match": "\\b_M_ARM64\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_ARM64.c" + }, + { + "match": "\\b_M_CEE\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_CEE.c" + }, + { + "match": "\\b_M_CEE_PURE\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_CEE_PURE.c" + }, + { + "match": "\\b_M_CEE_SAFE\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_CEE_SAFE.c" + }, + { + "match": "\\b_M_FP_EXCEPT\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_FP_EXCEPT.c" + }, + { + "match": "\\b_M_FP_FAST\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_FP_FAST.c" + }, + { + "match": "\\b_M_FP_PRECISE\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_FP_PRECISE.c" + }, + { + "match": "\\b_M_FP_STRICT\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_FP_STRICT.c" + }, + { + "match": "\\b_M_IX86\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_IX86.c" + }, + { + "match": "\\b_M_IX86_FP\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_IX86_FP.c" + }, + { + "match": "\\b_M_X64\\b", + "name": "entity.name.other.preprocessor.macro.predefined._M_X64.c" + }, + { + "match": "\\b_MANAGED\\b", + "name": "entity.name.other.preprocessor.macro.predefined._MANAGED.c" + }, + { + "match": "\\b_MSC_BUILD\\b", + "name": "entity.name.other.preprocessor.macro.predefined._MSC_BUILD.c" + }, + { + "match": "\\b_MSC_EXTENSIONS\\b", + "name": "entity.name.other.preprocessor.macro.predefined._MSC_EXTENSIONS.c" + }, + { + "match": "\\b_MSC_FULL_VER\\b", + "name": "entity.name.other.preprocessor.macro.predefined._MSC_FULL_VER.c" + }, + { + "match": "\\b_MSC_VER\\b", + "name": "entity.name.other.preprocessor.macro.predefined._MSC_VER.c" + }, + { + "match": "\\b_MSVC_LANG\\b", + "name": "entity.name.other.preprocessor.macro.predefined._MSVC_LANG.c" + }, + { + "match": "\\b__MSVC_RUNTIME_CHECKS\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__MSVC_RUNTIME_CHECKS.c" + }, + { + "match": "\\b_MT\\b", + "name": "entity.name.other.preprocessor.macro.predefined._MT.c" + }, + { + "match": "\\b_NATIVE_WCHAR_T_DEFINED\\b", + "name": "entity.name.other.preprocessor.macro.predefined._NATIVE_WCHAR_T_DEFINED.c" + }, + { + "match": "\\b_OPENMP\\b", + "name": "entity.name.other.preprocessor.macro.predefined._OPENMP.c" + }, + { + "match": "\\b_PREFAST\\b", + "name": "entity.name.other.preprocessor.macro.predefined._PREFAST.c" + }, + { + "match": "\\b__TIMESTAMP__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__TIMESTAMP__.c" + }, + { + "match": "\\b_VC_NO_DEFAULTLIB\\b", + "name": "entity.name.other.preprocessor.macro.predefined._VC_NO_DEFAULTLIB.c" + }, + { + "match": "\\b_WCHAR_T_DEFINED\\b", + "name": "entity.name.other.preprocessor.macro.predefined._WCHAR_T_DEFINED.c" + }, + { + "match": "\\b_WIN32\\b", + "name": "entity.name.other.preprocessor.macro.predefined._WIN32.c" + }, + { + "match": "\\b_WIN64\\b", + "name": "entity.name.other.preprocessor.macro.predefined._WIN64.c" + }, + { + "match": "\\b_WINRT_DLL\\b", + "name": "entity.name.other.preprocessor.macro.predefined._WINRT_DLL.c" + }, + { + "match": "\\b_ATL_VER\\b", + "name": "entity.name.other.preprocessor.macro.predefined._ATL_VER.c" + }, + { + "match": "\\b_MFC_VER\\b", + "name": "entity.name.other.preprocessor.macro.predefined._MFC_VER.c" + }, + { + "match": "\\b__GFORTRAN__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GFORTRAN__.c" + }, + { + "match": "\\b__GNUC__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GNUC__.c" + }, + { + "match": "\\b__GNUC_MINOR__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GNUC_MINOR__.c" + }, + { + "match": "\\b__GNUC_PATCHLEVEL__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GNUC_PATCHLEVEL__.c" + }, + { + "match": "\\b__GNUG__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GNUG__.c" + }, + { + "match": "\\b__STRICT_ANSI__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__STRICT_ANSI__.c" + }, + { + "match": "\\b__BASE_FILE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__BASE_FILE__.c" + }, + { + "match": "\\b__INCLUDE_LEVEL__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INCLUDE_LEVEL__.c" + }, + { + "match": "\\b__ELF__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__ELF__.c" + }, + { + "match": "\\b__VERSION__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__VERSION__.c" + }, + { + "match": "\\b__OPTIMIZE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__OPTIMIZE__.c" + }, + { + "match": "\\b__OPTIMIZE_SIZE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__OPTIMIZE_SIZE__.c" + }, + { + "match": "\\b__NO_INLINE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__NO_INLINE__.c" + }, + { + "match": "\\b__GNUC_STDC_INLINE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GNUC_STDC_INLINE__.c" + }, + { + "match": "\\b__CHAR_UNSIGNED__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__CHAR_UNSIGNED__.c" + }, + { + "match": "\\b__WCHAR_UNSIGNED__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__WCHAR_UNSIGNED__.c" + }, + { + "match": "\\b__REGISTER_PREFIX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__REGISTER_PREFIX__.c" + }, + { + "match": "\\b__REGISTER_PREFIX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__REGISTER_PREFIX__.c" + }, + { + "match": "\\b__SIZE_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZE_TYPE__.c" + }, + { + "match": "\\b__PTRDIFF_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__PTRDIFF_TYPE__.c" + }, + { + "match": "\\b__WCHAR_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__WCHAR_TYPE__.c" + }, + { + "match": "\\b__WINT_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__WINT_TYPE__.c" + }, + { + "match": "\\b__INTMAX_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INTMAX_TYPE__.c" + }, + { + "match": "\\b__UINTMAX_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINTMAX_TYPE__.c" + }, + { + "match": "\\b__SIG_ATOMIC_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIG_ATOMIC_TYPE__.c" + }, + { + "match": "\\b__INT8_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT8_TYPE__.c" + }, + { + "match": "\\b__INT16_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT16_TYPE__.c" + }, + { + "match": "\\b__INT32_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT32_TYPE__.c" + }, + { + "match": "\\b__INT64_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT64_TYPE__.c" + }, + { + "match": "\\b__UINT8_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT8_TYPE__.c" + }, + { + "match": "\\b__UINT16_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT16_TYPE__.c" + }, + { + "match": "\\b__UINT32_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT32_TYPE__.c" + }, + { + "match": "\\b__UINT64_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT64_TYPE__.c" + }, + { + "match": "\\b__INT_LEAST8_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST8_TYPE__.c" + }, + { + "match": "\\b__INT_LEAST16_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST16_TYPE__.c" + }, + { + "match": "\\b__INT_LEAST32_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST32_TYPE__.c" + }, + { + "match": "\\b__INT_LEAST64_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST64_TYPE__.c" + }, + { + "match": "\\b__UINT_LEAST8_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_LEAST8_TYPE__.c" + }, + { + "match": "\\b__UINT_LEAST16_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_LEAST16_TYPE__.c" + }, + { + "match": "\\b__UINT_LEAST32_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_LEAST32_TYPE__.c" + }, + { + "match": "\\b__UINT_LEAST64_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_LEAST64_TYPE__.c" + }, + { + "match": "\\b__INT_FAST8_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST8_TYPE__.c" + }, + { + "match": "\\b__INT_FAST16_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST16_TYPE__.c" + }, + { + "match": "\\b__INT_FAST32_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST32_TYPE__.c" + }, + { + "match": "\\b__INT_FAST64_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST64_TYPE__.c" + }, + { + "match": "\\b__UINT_FAST8_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_FAST8_TYPE__.c" + }, + { + "match": "\\b__UINT_FAST16_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_FAST16_TYPE__.c" + }, + { + "match": "\\b__UINT_FAST32_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_FAST32_TYPE__.c" + }, + { + "match": "\\b__UINT_FAST64_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_FAST64_TYPE__.c" + }, + { + "match": "\\b__INTPTR_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INTPTR_TYPE__.c" + }, + { + "match": "\\b__UINTPTR_TYPE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINTPTR_TYPE__.c" + }, + { + "match": "\\b__CHAR_BIT__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__CHAR_BIT__.c" + }, + { + "match": "\\b__SCHAR_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SCHAR_MAX__.c" + }, + { + "match": "\\b__WCHAR_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__WCHAR_MAX__.c" + }, + { + "match": "\\b__SHRT_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SHRT_MAX__.c" + }, + { + "match": "\\b__INT_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_MAX__.c" + }, + { + "match": "\\b__LONG_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__LONG_MAX__.c" + }, + { + "match": "\\b__LONG_LONG_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__LONG_LONG_MAX__.c" + }, + { + "match": "\\b__WINT_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__WINT_MAX__.c" + }, + { + "match": "\\b__SIZE_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZE_MAX__.c" + }, + { + "match": "\\b__PTRDIFF_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__PTRDIFF_MAX__.c" + }, + { + "match": "\\b__INTMAX_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INTMAX_MAX__.c" + }, + { + "match": "\\b__UINTMAX_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINTMAX_MAX__.c" + }, + { + "match": "\\b__SIG_ATOMIC_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIG_ATOMIC_MAX__.c" + }, + { + "match": "\\b__INT8_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT8_MAX__.c" + }, + { + "match": "\\b__INT16_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT16_MAX__.c" + }, + { + "match": "\\b__INT32_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT32_MAX__.c" + }, + { + "match": "\\b__INT64_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT64_MAX__.c" + }, + { + "match": "\\b__UINT8_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT8_MAX__.c" + }, + { + "match": "\\b__UINT16_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT16_MAX__.c" + }, + { + "match": "\\b__UINT32_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT32_MAX__.c" + }, + { + "match": "\\b__UINT64_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT64_MAX__.c" + }, + { + "match": "\\b__INT_LEAST8_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST8_MAX__.c" + }, + { + "match": "\\b__INT_LEAST16_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST16_MAX__.c" + }, + { + "match": "\\b__INT_LEAST32_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST32_MAX__.c" + }, + { + "match": "\\b__INT_LEAST64_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST64_MAX__.c" + }, + { + "match": "\\b__UINT_LEAST8_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_LEAST8_MAX__.c" + }, + { + "match": "\\b__UINT_LEAST16_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_LEAST16_MAX__.c" + }, + { + "match": "\\b__UINT_LEAST32_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_LEAST32_MAX__.c" + }, + { + "match": "\\b__UINT_LEAST64_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_LEAST64_MAX__.c" + }, + { + "match": "\\b__INT_FAST8_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST8_MAX__.c" + }, + { + "match": "\\b__INT_FAST16_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST16_MAX__.c" + }, + { + "match": "\\b__INT_FAST32_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST32_MAX__.c" + }, + { + "match": "\\b__INT_FAST64_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST64_MAX__.c" + }, + { + "match": "\\b__UINT_FAST8_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_FAST8_MAX__.c" + }, + { + "match": "\\b__UINT_FAST16_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_FAST16_MAX__.c" + }, + { + "match": "\\b__UINT_FAST32_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_FAST32_MAX__.c" + }, + { + "match": "\\b__UINT_FAST64_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINT_FAST64_MAX__.c" + }, + { + "match": "\\b__INTPTR_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INTPTR_MAX__.c" + }, + { + "match": "\\b__UINTPTR_MAX__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__UINTPTR_MAX__.c" + }, + { + "match": "\\b__WCHAR_MIN__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__WCHAR_MIN__.c" + }, + { + "match": "\\b__WINT_MIN__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__WINT_MIN__.c" + }, + { + "match": "\\b__SIG_ATOMIC_MIN__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIG_ATOMIC_MIN__.c" + }, + { + "match": "\\b__SCHAR_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SCHAR_WIDTH__.c" + }, + { + "match": "\\b__SHRT_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SHRT_WIDTH__.c" + }, + { + "match": "\\b__INT_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_WIDTH__.c" + }, + { + "match": "\\b__LONG_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__LONG_WIDTH__.c" + }, + { + "match": "\\b__LONG_LONG_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__LONG_LONG_WIDTH__.c" + }, + { + "match": "\\b__PTRDIFF_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__PTRDIFF_WIDTH__.c" + }, + { + "match": "\\b__SIG_ATOMIC_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIG_ATOMIC_WIDTH__.c" + }, + { + "match": "\\b__SIZE_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZE_WIDTH__.c" + }, + { + "match": "\\b__WCHAR_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__WCHAR_WIDTH__.c" + }, + { + "match": "\\b__WINT_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__WINT_WIDTH__.c" + }, + { + "match": "\\b__INT_LEAST8_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST8_WIDTH__.c" + }, + { + "match": "\\b__INT_LEAST16_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST16_WIDTH__.c" + }, + { + "match": "\\b__INT_LEAST32_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST32_WIDTH__.c" + }, + { + "match": "\\b__INT_LEAST64_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_LEAST64_WIDTH__.c" + }, + { + "match": "\\b__INT_FAST8_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST8_WIDTH__.c" + }, + { + "match": "\\b__INT_FAST16_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST16_WIDTH__.c" + }, + { + "match": "\\b__INT_FAST32_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST32_WIDTH__.c" + }, + { + "match": "\\b__INT_FAST64_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INT_FAST64_WIDTH__.c" + }, + { + "match": "\\b__INTPTR_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INTPTR_WIDTH__.c" + }, + { + "match": "\\b__INTMAX_WIDTH__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__INTMAX_WIDTH__.c" + }, + { + "match": "\\b__SIZEOF_INT__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_INT__.c" + }, + { + "match": "\\b__SIZEOF_LONG__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_LONG__.c" + }, + { + "match": "\\b__SIZEOF_LONG_LONG__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_LONG_LONG__.c" + }, + { + "match": "\\b__SIZEOF_SHORT__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_SHORT__.c" + }, + { + "match": "\\b__SIZEOF_POINTER__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_POINTER__.c" + }, + { + "match": "\\b__SIZEOF_FLOAT__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_FLOAT__.c" + }, + { + "match": "\\b__SIZEOF_DOUBLE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_DOUBLE__.c" + }, + { + "match": "\\b__SIZEOF_LONG_DOUBLE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_LONG_DOUBLE__.c" + }, + { + "match": "\\b__SIZEOF_SIZE_T__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_SIZE_T__.c" + }, + { + "match": "\\b__SIZEOF_WCHAR_T__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_WCHAR_T__.c" + }, + { + "match": "\\b__SIZEOF_WINT_T__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_WINT_T__.c" + }, + { + "match": "\\b__SIZEOF_PTRDIFF_T__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SIZEOF_PTRDIFF_T__.c" + }, + { + "match": "\\b__BYTE_ORDER__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__BYTE_ORDER__.c" + }, + { + "match": "\\b__ORDER_LITTLE_ENDIAN__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__ORDER_LITTLE_ENDIAN__.c" + }, + { + "match": "\\b__ORDER_BIG_ENDIAN__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__ORDER_BIG_ENDIAN__.c" + }, + { + "match": "\\b__ORDER_PDP_ENDIAN__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__ORDER_PDP_ENDIAN__.c" + }, + { + "match": "\\b__FLOAT_WORD_ORDER__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FLOAT_WORD_ORDER__.c" + }, + { + "match": "\\b__DEPRECATED\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__DEPRECATED.c" + }, + { + "match": "\\b__EXCEPTIONS\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__EXCEPTIONS.c" + }, + { + "match": "\\b__GXX_RTTI\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GXX_RTTI.c" + }, + { + "match": "\\b__USING_SJLJ_EXCEPTIONS__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__USING_SJLJ_EXCEPTIONS__.c" + }, + { + "match": "\\b__GXX_EXPERIMENTAL_CXX0X__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GXX_EXPERIMENTAL_CXX0X__.c" + }, + { + "match": "\\b__GXX_WEAK__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GXX_WEAK__.c" + }, + { + "match": "\\b__NEXT_RUNTIME__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__NEXT_RUNTIME__.c" + }, + { + "match": "\\b__LP64__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__LP64__.c" + }, + { + "match": "\\b_LP64\\b", + "name": "entity.name.other.preprocessor.macro.predefined._LP64.c" + }, + { + "match": "\\b__SSP__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SSP__.c" + }, + { + "match": "\\b__SSP_ALL__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SSP_ALL__.c" + }, + { + "match": "\\b__SSP_STRONG__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SSP_STRONG__.c" + }, + { + "match": "\\b__SSP_EXPLICIT__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SSP_EXPLICIT__.c" + }, + { + "match": "\\b__SANITIZE_ADDRESS__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SANITIZE_ADDRESS__.c" + }, + { + "match": "\\b__SANITIZE_THREAD__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__SANITIZE_THREAD__.c" + }, + { + "match": "\\b__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1.c" + }, + { + "match": "\\b__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2.c" + }, + { + "match": "\\b__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4.c" + }, + { + "match": "\\b__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8.c" + }, + { + "match": "\\b__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16.c" + }, + { + "match": "\\b__HAVE_SPECULATION_SAFE_VALUE\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__HAVE_SPECULATION_SAFE_VALUE.c" + }, + { + "match": "\\b__GCC_HAVE_DWARF2_CFI_ASM\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GCC_HAVE_DWARF2_CFI_ASM.c" + }, + { + "match": "\\b__FP_FAST_FMA\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FP_FAST_FMA.c" + }, + { + "match": "\\b__FP_FAST_FMAF\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FP_FAST_FMAF.c" + }, + { + "match": "\\b__FP_FAST_FMAL\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FP_FAST_FMAL.c" + }, + { + "match": "\\b__FP_FAST_FMAF16\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FP_FAST_FMAF16.c" + }, + { + "match": "\\b__FP_FAST_FMAF32\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FP_FAST_FMAF32.c" + }, + { + "match": "\\b__FP_FAST_FMAF64\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FP_FAST_FMAF64.c" + }, + { + "match": "\\b__FP_FAST_FMAF128\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FP_FAST_FMAF128.c" + }, + { + "match": "\\b__FP_FAST_FMAF32X\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FP_FAST_FMAF32X.c" + }, + { + "match": "\\b__FP_FAST_FMAF64X\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FP_FAST_FMAF64X.c" + }, + { + "match": "\\b__FP_FAST_FMAF128X\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FP_FAST_FMAF128X.c" + }, + { + "match": "\\b__GCC_IEC_559\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GCC_IEC_559.c" + }, + { + "match": "\\b__GCC_IEC_559_COMPLEX\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__GCC_IEC_559_COMPLEX.c" + }, + { + "match": "\\b__NO_MATH_ERRNO__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__NO_MATH_ERRNO__.c" + }, + { + "match": "\\b__has_builtin\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__has_builtin.c" + }, + { + "match": "\\b__has_feature\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__has_feature.c" + }, + { + "match": "\\b__has_extension\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__has_extension.c" + }, + { + "match": "\\b__has_cpp_attribute\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__has_cpp_attribute.c" + }, + { + "match": "\\b__has_c_attribute\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__has_c_attribute.c" + }, + { + "match": "\\b__has_attribute\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__has_attribute.c" + }, + { + "match": "\\b__has_declspec_attribute\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__has_declspec_attribute.c" + }, + { + "match": "\\b__is_identifier\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__is_identifier.c" + }, + { + "match": "\\b__has_include\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__has_include.c" + }, + { + "match": "\\b__has_include_next\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__has_include_next.c" + }, + { + "match": "\\b__has_warning\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__has_warning.c" + }, + { + "match": "\\b__BASE_FILE__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__BASE_FILE__.c" + }, + { + "match": "\\b__FILE_NAME__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__FILE_NAME__.c" + }, + { + "match": "\\b__clang__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__clang__.c" + }, + { + "match": "\\b__clang_major__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__clang_major__.c" + }, + { + "match": "\\b__clang_minor__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__clang_minor__.c" + }, + { + "match": "\\b__clang_patchlevel__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__clang_patchlevel__.c" + }, + { + "match": "\\b__clang_version__\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__clang_version__.c" + }, + { + "match": "\\b__fp16\\b", + "name": "entity.name.other.preprocessor.macro.predefined.__fp16.c" + }, + { + "match": "\\b_Float16\\b", + "name": "entity.name.other.preprocessor.macro.predefined._Float16.c" + }, + { + "match": "(\\b__([A-Z_])__\\b)", + "captures": { + "1": { + "name": "entity.name.other.preprocessor.macro.predefined.probably.$2.c" + } + } + } + ] + }, + "numbers": { + "begin": "(?\\]\\)]))\\s*([a-zA-Z_]\\w*)\\s*(?=(?:\\[\\]\\s*)?(?:,|\\)))", + "captures": { + "1": { + "name": "variable.parameter.probably.c" + } + } + }, + "access-method": { + "name": "meta.function-call.member.c", + "begin": "([a-zA-Z_][a-zA-Z_0-9]*|(?<=[\\]\\)]))\\s*(?:(\\.)|(->))((?:(?:[a-zA-Z_][a-zA-Z_0-9]*)\\s*(?:(?:\\.)|(?:->)))*)\\s*([a-zA-Z_][a-zA-Z_0-9]*)(\\()", + "beginCaptures": { + "1": { + "name": "variable.object.c" + }, + "2": { + "name": "punctuation.separator.dot-access.c" + }, + "3": { + "name": "punctuation.separator.pointer-access.c" + }, + "4": { + "patterns": [ + { + "match": "\\.", + "name": "punctuation.separator.dot-access.c" + }, + { + "match": "->", + "name": "punctuation.separator.pointer-access.c" + }, + { + "match": "[a-zA-Z_][a-zA-Z_0-9]*", + "name": "variable.object.c" + }, + { + "name": "everything.else.c", + "match": ".+" + } + ] + }, + "5": { + "name": "entity.name.function.member.c" + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.function.member.c" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.arguments.end.bracket.round.function.member.c" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] }, "block": { "patterns": [ @@ -352,25 +2241,36 @@ "include": "#preprocessor-rule-conditional-block" }, { - "include": "#access" + "include": "#method_access" }, { - "include": "#libc" + "include": "#member_access" }, { "include": "#c_function_call" }, { - "captures": { + "name": "meta.initialization.c", + "begin": "(?x)\n(?:\n (?:\n\t(?=\\s)(?=+!]+ | \\(\\) | \\[\\]))\n)\n\\s*(\\() # opening bracket", + "beginCaptures": { "1": { "name": "variable.other.c" }, "2": { - "name": "punctuation.definition.parameters.c" + "name": "punctuation.section.parens.begin.bracket.round.initialization.c" } }, - "match": "(?x)\n(?:\n (?:\n (?=\\s)(?=+!]+ | \\(\\) | \\[\\]))\n)\n\\s*(\\() # opening bracket", - "name": "meta.initialization.c" + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.initialization.c" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] }, { "begin": "{", @@ -400,7 +2300,7 @@ ] }, "c_function_call": { - "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate)\\s*\\()\n(?=\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++\\s*\\( # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", + "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate|and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas)\\s*\\()\n(?=\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++\\s*\\( # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", "end": "(?<=\\))(?!\\w)", "name": "meta.function-call.c", "patterns": [ @@ -435,10 +2335,6 @@ }, "name": "comment.block.c" }, - { - "match": "\\*/.*\\n", - "name": "invalid.illegal.stray-comment-end.c" - }, { "captures": { "1": { @@ -446,13 +2342,13 @@ } }, "match": "^// =(\\s*.*?)\\s*=\\s*$\\n?", - "name": "comment.line.banner.cpp" + "name": "comment.line.banner.c" }, { "begin": "(^[ \\t]+)?(?=//)", "beginCaptures": { "1": { - "name": "punctuation.whitespace.comment.leading.cpp" + "name": "punctuation.whitespace.comment.leading.c" } }, "end": "(?!\\G)", @@ -461,11 +2357,11 @@ "begin": "//", "beginCaptures": { "0": { - "name": "punctuation.definition.comment.cpp" + "name": "punctuation.definition.comment.c" } }, "end": "(?=\\n)", - "name": "comment.line.double-slash.cpp", + "name": "comment.line.double-slash.c", "patterns": [ { "include": "#line_continuation_character" @@ -488,17 +2384,6 @@ } ] }, - "libc": { - "captures": { - "1": { - "name": "punctuation.whitespace.support.function.leading.c" - }, - "2": { - "name": "support.function.C99.c" - } - }, - "match": "(?x) (\\s*) \\b\n(_Exit|(?:nearbyint|nextafter|nexttoward|netoward|nan)[fl]?|a(?:cos|sin)h?[fl]?|abort|abs|asctime|assert\n|atan(?:[h2]?[fl]?)?|atexit|ato[ifl]|atoll|bsearch|btowc|cabs[fl]?|cacos|cacos[fl]|cacosh[fl]?\n|calloc|carg[fl]?|casinh?[fl]?|catanh?[fl]?|cbrt[fl]?|ccosh?[fl]?|ceil[fl]?|cexp[fl]?|cimag[fl]?\n|clearerr|clock|clog[fl]?|conj[fl]?|copysign[fl]?|cosh?[fl]?|cpow[fl]?|cproj[fl]?|creal[fl]?\n|csinh?[fl]?|csqrt[fl]?|ctanh?[fl]?|ctime|difftime|div|erfc?[fl]?|exit|fabs[fl]?\n|exp(?:2[fl]?|[fl]|m1[fl]?)?|fclose|fdim[fl]?|fe[gs]et(?:env|exceptflag|round)|feclearexcept\n|feholdexcept|feof|feraiseexcept|ferror|fetestexcept|feupdateenv|fflush|fgetpos|fgetw?[sc]\n|floor[fl]?|fmax?[fl]?|fmin[fl]?|fmod[fl]?|fopen|fpclassify|fprintf|fputw?[sc]|fread|free|freopen\n|frexp[fl]?|fscanf|fseek|fsetpos|ftell|fwide|fwprintf|fwrite|fwscanf|genv|get[sc]|getchar|gmtime\n|gwc|gwchar|hypot[fl]?|ilogb[fl]?|imaxabs|imaxdiv|isalnum|isalpha|isblank|iscntrl|isdigit|isfinite\n|isgraph|isgreater|isgreaterequal|isinf|isless(?:equal|greater)?|isw?lower|isnan|isnormal|isw?print\n|isw?punct|isw?space|isunordered|isw?upper|iswalnum|iswalpha|iswblank|iswcntrl|iswctype|iswdigit|iswgraph\n|isw?xdigit|labs|ldexp[fl]?|ldiv|lgamma[fl]?|llabs|lldiv|llrint[fl]?|llround[fl]?|localeconv|localtime\n|log[2b]?[fl]?|log1[p0][fl]?|longjmp|lrint[fl]?|lround[fl]?|malloc|mbr?len|mbr?towc|mbsinit|mbsrtowcs\n|mbstowcs|memchr|memcmp|memcpy|memmove|memset|mktime|modf[fl]?|perror|pow[fl]?|printf|puts|putw?c(?:har)?\n|qsort|raise|rand|remainder[fl]?|realloc|remove|remquo[fl]?|rename|rewind|rint[fl]?|round[fl]?|scalbl?n[fl]?\n|scanf|setbuf|setjmp|setlocale|setvbuf|signal|signbit|sinh?[fl]?|snprintf|sprintf|sqrt[fl]?|srand|sscanf\n|strcat|strchr|strcmp|strcoll|strcpy|strcspn|strerror|strftime|strlen|strncat|strncmp|strncpy|strpbrk\n|strrchr|strspn|strstr|strto[kdf]|strtoimax|strtol[dl]?|strtoull?|strtoumax|strxfrm|swprintf|swscanf\n|system|tan|tan[fl]|tanh[fl]?|tgamma[fl]?|time|tmpfile|tmpnam|tolower|toupper|trunc[fl]?|ungetw?c|va_arg\n|va_copy|va_end|va_start|vfw?printf|vfw?scanf|vprintf|vscanf|vsnprintf|vsprintf|vsscanf|vswprintf|vswscanf\n|vwprintf|vwscanf|wcrtomb|wcscat|wcschr|wcscmp|wcscoll|wcscpy|wcscspn|wcsftime|wcslen|wcsncat|wcsncmp|wcsncpy\n|wcspbrk|wcsrchr|wcsrtombs|wcsspn|wcsstr|wcsto[dkf]|wcstoimax|wcstol[dl]?|wcstombs|wcstoull?|wcstoumax|wcsxfrm\n|wctom?b|wmem(?:set|chr|cpy|cmp|move)|wprintf|wscanf)\\b" - }, "line_continuation_character": { "patterns": [ { @@ -511,15 +2396,8 @@ } ] }, - "numbers": { - "patterns": [ - { - "match": "\\b((0(x|X)[0-9a-fA-F]([0-9a-fA-F']*[0-9a-fA-F])?)|(0(b|B)[01]([01']*[01])?)|(([0-9]([0-9']*[0-9])?\\.?[0-9]*([0-9']*[0-9])?)|(\\.[0-9]([0-9']*[0-9])?))((e|E)(\\+|-)?[0-9]([0-9']*[0-9])?)?)(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b", - "name": "constant.numeric.c" - } - ] - }, "parens": { + "name": "meta.parens.c", "begin": "\\(", "beginCaptures": { "0": { @@ -539,6 +2417,7 @@ ] }, "parens-block": { + "name": "meta.parens.block.c", "begin": "\\(", "beginCaptures": { "0": { @@ -554,6 +2433,10 @@ "patterns": [ { "include": "#block_innards" + }, + { + "match": "(?-mix:(?=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", + "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate|and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas|asm|__asm__|auto|bool|_Bool|char|_Complex|double|enum|float|_Imaginary|int|long|short|signed|struct|typedef|union|unsigned|void)\\s*\\()\n(?=\n (?:[A-Za-z_][A-Za-z0-9_]*+|::)++\\s*\\( # actual name\n |\n (?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", "end": "(?<=\\))(?!\\w)|(?=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate|and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas)\\s*\\()\n(\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++ # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", "beginCaptures": { "1": { "name": "entity.name.function.c" @@ -1846,7 +3827,8 @@ "include": "#vararg_ellipses" }, { - "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate)\\s*\\()\n(\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++ # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "name": "meta.function.definition.parameters.c", + "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate|and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas)\\s*\\()\n(\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++ # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", "beginCaptures": { "1": { "name": "entity.name.function.c" @@ -1862,6 +3844,9 @@ } }, "patterns": [ + { + "include": "#probably_a_parameter" + }, { "include": "#function-innards" } @@ -1900,13 +3885,16 @@ "include": "#storage_types" }, { - "include": "#access" + "include": "#method_access" + }, + { + "include": "#member_access" }, { "include": "#operators" }, { - "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate)\\s*\\()\n(\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++ # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate|and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas)\\s*\\()\n(\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++ # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", "beginCaptures": { "1": { "name": "entity.name.function.c" diff --git a/extensions/cpp/syntaxes/cpp.tmLanguage.json b/extensions/cpp/syntaxes/cpp.tmLanguage.json index f29bc255ba8..5e0af3c03ef 100644 --- a/extensions/cpp/syntaxes/cpp.tmLanguage.json +++ b/extensions/cpp/syntaxes/cpp.tmLanguage.json @@ -1,394 +1,14874 @@ { "information_for_contributors": [ - "This file has been converted from https://github.com/atom/language-c/blob/master/grammars/c%2B%2B.cson", + "This file has been converted from https://github.com/jeff-hykin/cpp-textmate-grammar/blob/master//syntaxes/cpp.tmLanguage.json", "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/atom/language-c/commit/3a269f88b12e512fb9495dc006a1dabf325d3d7f", + "version": "https://github.com/jeff-hykin/cpp-textmate-grammar/commit/cbd71f90cd9be0f99ddc9b0f65cec62fc3ada6d1", "name": "C++", "scopeName": "source.cpp", "patterns": [ { - "include": "#special_block" + "include": "#ever_present_context" }, { - "include": "#strings" + "include": "#constructor_root" }, { - "match": "\\b(friend|explicit|virtual|override|final|noexcept)\\b", - "name": "storage.modifier.cpp" + "include": "#destructor_root" }, { - "match": "\\b(private:|protected:|public:)", - "name": "storage.modifier.cpp" + "include": "#function_definition" }, { - "match": "\\b(catch|operator|try|throw|using)\\b", - "name": "keyword.control.cpp" + "include": "#operator_overload" }, { - "match": "\\bdelete\\b(\\s*\\[\\])?|\\bnew\\b(?!])", - "name": "keyword.control.cpp" + "include": "#using_namespace" }, { - "match": "\\b(f|m)[A-Z]\\w*\\b", - "name": "variable.other.readwrite.member.cpp" + "include": "#type_alias" }, { - "match": "\\bthis\\b", - "name": "variable.language.this.cpp" + "include": "#using_name" }, { - "match": "\\bnullptr\\b", - "name": "constant.language.cpp" + "include": "#namespace_alias" }, { - "match": "\\btemplate\\b\\s*", - "name": "storage.type.template.cpp" + "include": "#namespace_block" }, { - "match": "\\b(const_cast|dynamic_cast|reinterpret_cast|static_cast)\\b\\s*", - "name": "keyword.operator.cast.cpp" + "include": "#extern_block" }, { - "match": "::", - "name": "punctuation.separator.namespace.access.cpp" + "include": "#typedef_class" }, { - "match": "\\b(and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas)\\b", - "name": "keyword.operator.cpp" + "include": "#typedef_struct" }, { - "match": "\\b(class|decltype|wchar_t|char16_t|char32_t)\\b", - "name": "storage.type.cpp" + "include": "#typedef_union" }, { - "match": "\\b(constexpr|export|mutable|typename|thread_local)\\b", - "name": "storage.modifier.cpp" + "include": "#typedef_function_pointer" }, { - "begin": "(?x)\n(?:\n ^ | # beginning of line\n (?:(?", - "name": "meta.angle-brackets.cpp", + "inline_comment": { + "match": "(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/))", + "captures": { + "1": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "2": { + "name": "comment.block.cpp" + }, + "3": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + "semicolon": { + "match": ";", + "name": "punctuation.terminator.statement.cpp" + }, + "comma": { + "match": ",", + "name": "punctuation.separator.delimiter.comma.cpp" + }, + "assignment_operator": { + "match": "\\=", + "name": "keyword.operator.assignment.cpp" + }, + "ever_present_context": { "patterns": [ { - "include": "#angle_brackets" + "include": "#single_line_macro" }, { - "include": "$base" + "include": "#preprocessor_rule_enabled" + }, + { + "include": "#preprocessor_rule_disabled" + }, + { + "include": "#preprocessor_rule_conditional" + }, + { + "include": "#meta_preprocessor_macro" + }, + { + "include": "#meta_preprocessor_diagnostic" + }, + { + "include": "#meta_preprocessor_include" + }, + { + "include": "#pragma_mark" + }, + { + "include": "#meta_preprocessor_line" + }, + { + "include": "#meta_preprocessor_undef" + }, + { + "include": "#meta_preprocessor_pragma" + }, + { + "include": "#hacky_fix_for_stray_directive" + }, + { + "include": "#comments" + }, + { + "include": "#line_continuation_character" } ] }, - "block": { - "begin": "\\{", - "beginCaptures": { - "0": { - "name": "punctuation.section.block.begin.bracket.curly.c" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.section.block.end.bracket.curly.c" - } - }, - "name": "meta.block.cpp", + "function_body_context": { "patterns": [ { + "include": "#ever_present_context" + }, + { + "include": "#using_namespace" + }, + { + "include": "#type_alias" + }, + { + "include": "#using_name" + }, + { + "include": "#namespace_alias" + }, + { + "include": "#typedef_class" + }, + { + "include": "#typedef_struct" + }, + { + "include": "#typedef_union" + }, + { + "include": "#typedef_function_pointer" + }, + { + "include": "#typedef_keyword" + }, + { + "include": "#standard_declares" + }, + { + "include": "#class_block" + }, + { + "include": "#struct_block" + }, + { + "include": "#union_block" + }, + { + "include": "#enum_block" + }, + { + "include": "#access_control_keywords" + }, + { + "include": "#block" + }, + { + "include": "#static_assert" + }, + { + "include": "#assembly" + }, + { + "include": "#function_pointer" + }, + { + "include": "#switch_statement" + }, + { + "include": "#goto_statement" + }, + { + "include": "#evaluation_context" + }, + { + "include": "#label" + } + ] + }, + "evaluation_context": { + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#string_context" + }, + { + "include": "#number_literal" + }, + { + "include": "#string_context_c" + }, + { + "include": "#method_access" + }, + { + "include": "#member_access" + }, + { + "include": "#predefined_macros" + }, + { + "include": "#operators" + }, + { + "include": "#memory_operators" + }, + { + "include": "#wordlike_operators" + }, + { + "include": "#type_casting_operators" + }, + { + "include": "#control_flow_keywords" + }, + { + "include": "#exception_keywords" + }, + { + "include": "#the_this_keyword" + }, + { + "include": "#language_constants" + }, + { + "include": "#builtin_storage_type_initilizer" + }, + { + "include": "#storage_types" + }, + { + "include": "#qualifiers_and_specifiers_post_parameters" + }, + { + "include": "#functional_specifiers_pre_parameters" + }, + { + "include": "#misc_storage_modifiers" + }, + { + "include": "#lambdas" + }, + { + "include": "#attributes_context" + }, + { + "include": "#parentheses" + }, + { + "include": "#function_call" + }, + { + "include": "#scope_resolution_inner_generated" + }, + { + "include": "#square_brackets" + }, + { + "include": "#empty_square_brackets" + }, + { + "include": "#semicolon" + }, + { + "include": "#comma" + } + ] + }, + "function_parameter_context": { + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#parameter" + }, + { + "include": "#comma" + } + ] + }, + "template_definition_context": { + "patterns": [ + { + "include": "#scope_resolution_template_definition_inner_generated" + }, + { + "include": "#template_definition_argument" + }, + { + "include": "#template_argument_defaulted" + }, + { + "include": "#template_call_innards" + }, + { + "include": "#evaluation_context" + } + ] + }, + "template_call_context": { + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#template_call_range" + }, + { + "include": "#storage_types" + }, + { + "include": "#language_constants" + }, + { + "include": "#scope_resolution_template_call_inner_generated" + }, + { + "include": "#operators" + }, + { + "include": "#number_literal" + }, + { + "include": "#string_context" + }, + { + "include": "#comma_in_template_argument" + }, + { + "include": "#qualified_type" + } + ] + }, + "attributes_context": { + "patterns": [ + { + "include": "#cpp_attributes" + }, + { + "include": "#gcc_attributes" + }, + { + "include": "#ms_attributes" + }, + { + "include": "#alignas_attribute" + } + ] + }, + "storage_types": { + "patterns": [ + { + "include": "#storage_specifiers" + }, + { + "include": "#primitive_types" + }, + { + "include": "#non_primitive_types" + }, + { + "include": "#pthread_types" + }, + { + "include": "#posix_reserved_types" + }, + { + "include": "#decltype" + }, + { + "include": "#typename" + } + ] + }, + "block_comment": { + "name": "comment.block.cpp", + "begin": "\\s*+(\\/\\*)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.begin.cpp" + } + }, + "end": "(\\*\\/)", + "endCaptures": { + "1": { + "name": "punctuation.definition.comment.end.cpp" + } + } + }, + "line_comment": { + "name": "comment.line.double-slash.cpp", + "begin": "\\s*+(\\/\\/)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.cpp" + } + }, + "end": "(?<=\\n)(?[#;\\/=*C~]+)(?![#;\\/=*C~]))\\s*.+\\s*\\8\\s*(?:\\n|$)))|(^\\s*((\\/\\*)\\s*?((?>[#;\\/=*C~]+)(?![#;\\/=*C~]))\\s*.+\\s*\\8\\s*\\*\\/)))", + "captures": { + "1": { + "name": "meta.toc-list.banner.double-slash.cpp" + }, + "2": { + "name": "comment.line.double-slash.cpp" + }, + "3": { + "name": "punctuation.definition.comment.cpp" + }, + "4": { + "name": "meta.banner.character.cpp" + }, + "5": { + "name": "meta.toc-list.banner.block.cpp" + }, + "6": { + "name": "comment.line.block.cpp" + }, + "7": { + "name": "punctuation.definition.comment.cpp" + }, + "8": { + "name": "meta.banner.character.cpp" + } + } + }, + "invalid_comment_end": { + "match": "\\*\\/", + "name": "invalid.illegal.unexpected.punctuation.definition.comment.end.cpp" + }, + "comments": { + "patterns": [ + { + "include": "#emacs_file_banner" + }, + { + "include": "#block_comment" + }, + { + "include": "#line_comment" + }, + { + "include": "#invalid_comment_end" + } + ] + }, + "number_literal": { + "begin": "(?|\\[|\\]|=))", - "name": "meta.namespace-block.cpp", + } + }, + { + "match": "(\\G0)((?:[0-7]|((?<=[0-9a-fA-F])'(?=[0-9a-fA-F])))+)((?:(?:(?:(?:(?:[uU]|[uU]ll?)|[uU]LL?)|ll?[uU]?)|LL?[uU]?)|[fF])(?!\\w))?((?:\\w(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "name": "keyword.operator.functionlike.cpp keyword.other.decltype.cpp storage.type.decltype.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.decltype.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.decltype.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "decltype": { + "contentName": "meta.arguments.decltype.cpp", + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "name": "keyword.operator.functionlike.cpp keyword.other.decltype.cpp storage.type.decltype.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.decltype.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.decltype.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "pthread_types": { + "match": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(((?:private|protected|public))\\s*(:))", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "storage.type.modifier.access.control.$6.cpp" + }, + "7": { + "name": "punctuation.separator.colon.access.control.cpp" + } + } + }, + "exception_keywords": { + "match": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:(?:(delete)\\s*(\\[\\])|(delete))|(new))(?!\\w))", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "keyword.operator.wordlike.cpp" + }, + "6": { + "name": "keyword.operator.delete.array.cpp" + }, + "7": { + "name": "keyword.operator.delete.array.bracket.cpp" + }, + "8": { + "name": "keyword.operator.delete.cpp" + }, + "9": { + "name": "keyword.operator.new.cpp" + } + } + }, + "control_flow_keywords": { + "match": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)", + "captures": { + "1": { + "name": "keyword.control.goto.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "entity.name.label.call.cpp" + } + } + }, + "label": { + "match": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(:)", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "entity.name.label.cpp" + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "10": { + "name": "punctuation.separator.label.cpp" + } + } + }, + "default_statement": { + "name": "meta.conditional.case.cpp", + "begin": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "punctuation.section.parens.begin.bracket.round.conditional.switch.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.conditional.switch.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + }, + { + "include": "#c_conditional_context" + } + ] + }, + "switch_statement": { + "name": "meta.block.switch.cpp", + "begin": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?|\\?\\?>)|(?=[;>\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.switch.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.switch.cpp" + } + }, + "patterns": [ + { + "include": "#switch_conditional_parentheses" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.body.switch.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.switch.cpp" + } + }, + "patterns": [ + { + "include": "#default_statement" + }, + { + "include": "#case_statement" + }, + { + "include": "$self" + }, + { + "include": "#block_innards" + } + ] + }, + { + "name": "meta.tail.switch.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "cpp_attributes": { + "name": "support.other.attribute.cpp", + "begin": "(\\[\\[)", + "beginCaptures": { + "1": { + "name": "punctuation.section.attribute.begin.cpp" + } + }, + "end": "(\\]\\])", + "endCaptures": { + "1": { + "name": "punctuation.section.attribute.end.cpp" + } + }, + "patterns": [ + { + "include": "#attributes_context" + }, + { + "begin": "\\(", + "end": "\\)", + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#string_context_c" + } + ] + }, + { + "match": "(using)\\s+((?(?:(?>[^<>]*)\\g<1>?)+)>)\\s*", + "captures": { + "0": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + } + } + }, + "template_call_range": { + "name": "meta.template.call.cpp", + "begin": "(<)", + "beginCaptures": { + "1": { + "name": "punctuation.section.angle-brackets.begin.template.call.cpp" + } + }, + "end": "(>)", + "endCaptures": { + "1": { + "name": "punctuation.section.angle-brackets.end.template.call.cpp" + } + }, + "patterns": [ + { + "include": "#template_call_context" + } + ] + }, + "template_isolated_definition": { + "match": "(?\\s*$)", + "captures": { + "1": { + "name": "storage.type.template.cpp" + }, + "2": { + "name": "punctuation.section.angle-brackets.start.template.definition.cpp" + }, + "3": { + "name": "meta.template.definition.cpp", + "patterns": [ + { + "include": "#template_definition_context" + } + ] + }, + "4": { + "name": "punctuation.section.angle-brackets.end.template.definition.cpp" + } + } + }, + "template_definition": { + "name": "meta.template.definition.cpp", + "begin": "(?)", + "endCaptures": { + "1": { + "name": "punctuation.section.angle-brackets.end.template.definition.cpp" + } + }, + "patterns": [ + { + "begin": "((?<=\\w)\\s*<)", + "beginCaptures": { + "1": { + "name": "punctuation.section.angle-brackets.begin.template.call.cpp" + } + }, + "end": "(>)", + "endCaptures": { + "1": { + "name": "punctuation.section.angle-brackets.begin.template.call.cpp" + } + }, + "patterns": [ + { + "include": "#template_call_context" + } + ] + }, + { + "include": "#template_definition_context" + } + ] + }, + "template_argument_defaulted": { + "match": "(?<=<|,)\\s*((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s+)*)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*([=])", + "captures": { + "1": { + "name": "storage.type.template.cpp" + }, + "2": { + "name": "entity.name.type.template.cpp" + }, + "3": { + "name": "keyword.operator.assignment.cpp" + } + } + }, + "template_definition_argument": { + "match": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)|((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s+)+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))|((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*(\\.\\.\\.)\\s*((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*(?:(,)|(?=>|$))", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "storage.type.template.argument.$5.cpp" + }, + "6": { + "patterns": [ + { + "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", + "name": "storage.type.template.argument.$0.cpp" + } + ] + }, + "7": { + "name": "entity.name.type.template.cpp" + }, + "8": { + "name": "storage.type.template.cpp" + }, + "9": { + "name": "punctuation.vararg-ellipses.template.definition.cpp" + }, + "10": { + "name": "entity.name.type.template.cpp" + }, + "11": { + "name": "punctuation.separator.delimiter.comma.template.argument.cpp" + } + } + }, + "scope_resolution": { + "match": "(::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<4>?)+)>)\\s*)?::)*\\s*+", + "captures": { + "0": { + "patterns": [ + { + "include": "#scope_resolution_inner_generated" + } + ] + }, + "1": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, + "3": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + } + } + }, + "scope_resolution_inner_generated": { + "match": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?(::)", + "captures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution_inner_generated" + } + ] + }, + "2": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, + "4": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "6": { + "name": "entity.name.scope-resolution.cpp" + }, + "7": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "9": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + } + } + }, + "scope_resolution_template_call": { + "match": "(::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<4>?)+)>)\\s*)?::)*\\s*+", + "captures": { + "0": { + "patterns": [ + { + "include": "#scope_resolution_template_call_inner_generated" + } + ] + }, + "1": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.template.call.cpp" + }, + "3": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + } + } + }, + "scope_resolution_template_call_inner_generated": { + "match": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?(::)", + "captures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution_template_call_inner_generated" + } + ] + }, + "2": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.template.call.cpp" + }, + "4": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "6": { + "name": "entity.name.scope-resolution.template.call.cpp" + }, + "7": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "9": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.template.call.cpp" + } + } + }, + "scope_resolution_template_definition": { + "match": "(::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<4>?)+)>)\\s*)?::)*\\s*+", + "captures": { + "0": { + "patterns": [ + { + "include": "#scope_resolution_template_definition_inner_generated" + } + ] + }, + "1": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.template.definition.cpp" + }, + "3": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + } + } + }, + "scope_resolution_template_definition_inner_generated": { + "match": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?(::)", + "captures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution_template_definition_inner_generated" + } + ] + }, + "2": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.template.definition.cpp" + }, + "4": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "6": { + "name": "entity.name.scope-resolution.template.definition.cpp" + }, + "7": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "9": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.template.definition.cpp" + } + } + }, + "scope_resolution_function_call": { + "match": "(::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<4>?)+)>)\\s*)?::)*\\s*+", + "captures": { + "0": { + "patterns": [ + { + "include": "#scope_resolution_function_call_inner_generated" + } + ] + }, + "1": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.call.cpp" + }, + "3": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + } + } + }, + "scope_resolution_function_call_inner_generated": { + "match": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?(::)", + "captures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution_function_call_inner_generated" + } + ] + }, + "2": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.call.cpp" + }, + "4": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "6": { + "name": "entity.name.scope-resolution.function.call.cpp" + }, + "7": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "9": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.call.cpp" + } + } + }, + "scope_resolution_function_definition": { + "match": "(::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<4>?)+)>)\\s*)?::)*\\s*+", + "captures": { + "0": { + "patterns": [ + { + "include": "#scope_resolution_function_definition_inner_generated" + } + ] + }, + "1": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.definition.cpp" + }, + "3": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + } + } + }, + "scope_resolution_function_definition_inner_generated": { + "match": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?(::)", + "captures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution_function_definition_inner_generated" + } + ] + }, + "2": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.definition.cpp" + }, + "4": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "6": { + "name": "entity.name.scope-resolution.function.definition.cpp" + }, + "7": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "9": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.definition.cpp" + } + } + }, + "scope_resolution_namespace_alias": { + "match": "(::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<4>?)+)>)\\s*)?::)*\\s*+", + "captures": { + "0": { + "patterns": [ + { + "include": "#scope_resolution_namespace_alias_inner_generated" + } + ] + }, + "1": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.namespace.alias.cpp" + }, + "3": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + } + } + }, + "scope_resolution_namespace_alias_inner_generated": { + "match": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?(::)", + "captures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution_namespace_alias_inner_generated" + } + ] + }, + "2": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.namespace.alias.cpp" + }, + "4": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "6": { + "name": "entity.name.scope-resolution.namespace.alias.cpp" + }, + "7": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "9": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.namespace.alias.cpp" + } + } + }, + "scope_resolution_namespace_using": { + "match": "(::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<4>?)+)>)\\s*)?::)*\\s*+", + "captures": { + "0": { + "patterns": [ + { + "include": "#scope_resolution_namespace_using_inner_generated" + } + ] + }, + "1": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.namespace.using.cpp" + }, + "3": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + } + } + }, + "scope_resolution_namespace_using_inner_generated": { + "match": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?(::)", + "captures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution_namespace_using_inner_generated" + } + ] + }, + "2": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.namespace.using.cpp" + }, + "4": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "6": { + "name": "entity.name.scope-resolution.namespace.using.cpp" + }, + "7": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "9": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.namespace.using.cpp" + } + } + }, + "scope_resolution_namespace_block": { + "match": "(::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<4>?)+)>)\\s*)?::)*\\s*+", + "captures": { + "0": { + "patterns": [ + { + "include": "#scope_resolution_namespace_block_inner_generated" + } + ] + }, + "1": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.namespace.block.cpp" + }, + "3": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + } + } + }, + "scope_resolution_namespace_block_inner_generated": { + "match": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?(::)", + "captures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution_namespace_block_inner_generated" + } + ] + }, + "2": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.namespace.block.cpp" + }, + "4": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "6": { + "name": "entity.name.scope-resolution.namespace.block.cpp" + }, + "7": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "9": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.namespace.block.cpp" + } + } + }, + "scope_resolution_parameter": { + "match": "(::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<4>?)+)>)\\s*)?::)*\\s*+", + "captures": { + "0": { + "patterns": [ + { + "include": "#scope_resolution_parameter_inner_generated" + } + ] + }, + "1": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.parameter.cpp" + }, + "3": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + } + } + }, + "scope_resolution_parameter_inner_generated": { + "match": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?(::)", + "captures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution_parameter_inner_generated" + } + ] + }, + "2": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.parameter.cpp" + }, + "4": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "6": { + "name": "entity.name.scope-resolution.parameter.cpp" + }, + "7": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "9": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.parameter.cpp" + } + } + }, + "scope_resolution_function_definition_operator_overload": { + "match": "(::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<4>?)+)>)\\s*)?::)*\\s*+", + "captures": { + "0": { + "patterns": [ + { + "include": "#scope_resolution_function_definition_operator_overload_inner_generated" + } + ] + }, + "1": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.definition.operator-overload.cpp" + }, + "3": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + } + } + }, + "scope_resolution_function_definition_operator_overload_inner_generated": { + "match": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<8>?)+)>)\\s*)?(::)", + "captures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution_function_definition_operator_overload_inner_generated" + } + ] + }, + "2": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.definition.operator-overload.cpp" + }, + "4": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "6": { + "name": "entity.name.scope-resolution.function.definition.operator-overload.cpp" + }, + "7": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "9": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.definition.operator-overload.cpp" + } + } + }, + "qualified_type": { + "match": "\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<26>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<26>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<26>?)+)>)\\s*)?(?![\\w<:.])", + "captures": { + "0": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(?![\\w<:.]))(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?", + "captures": { + "1": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] } }, - "end": "\\}", + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "29": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "30": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "31": { + "name": "comment.block.cpp" + }, + "32": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "33": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "34": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "35": { + "name": "comment.block.cpp" + }, + "36": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + "type_alias": { + "match": "(using)\\s*(?!namespace)(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<58>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<58>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<58>?)+)>)\\s*)?(?![\\w<:.]))\\s*(\\=)\\s*((?:typename)?)\\s*((?:(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<58>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<58>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<58>?)+)>)\\s*)?(?![\\w<:.]))|(.*(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?(?:(\\[)(\\w*)(\\])\\s*)?\\s*(?:(;)|\\n)", + "captures": { + "1": { + "name": "keyword.other.using.directive.cpp" + }, + "2": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "61": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "62": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "63": { + "name": "comment.block.cpp" + }, + "64": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "65": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "66": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "67": { + "name": "comment.block.cpp" + }, + "68": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "69": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "70": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "71": { + "name": "comment.block.cpp" + }, + "72": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "73": { + "name": "punctuation.definition.begin.bracket.square.cpp" + }, + "74": { + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "75": { + "name": "punctuation.definition.end.bracket.square.cpp" + }, + "76": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "name": "meta.declaration.type.alias.cpp" + }, + "typename": { + "match": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<36>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<36>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<36>?)+)>)\\s*)?(?![\\w<:.]))", + "captures": { + "1": { + "name": "storage.modifier.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "10": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?(?:((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<69>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<69>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<69>?)+)>)\\s*)?(?![\\w<:.]))(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<69>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\())", + "beginCaptures": { + "1": { + "name": "meta.head.function.definition.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "storage.type.template.cpp" + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "name": "storage.modifier.$11.cpp" + }, + "12": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "13": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "14": { + "name": "comment.block.cpp" + }, + "15": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "16": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "44": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "45": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "46": { + "name": "comment.block.cpp" + }, + "47": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "48": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "49": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "50": { + "name": "comment.block.cpp" + }, + "51": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "52": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "53": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "54": { + "name": "comment.block.cpp" + }, + "55": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "56": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "57": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "58": { + "name": "comment.block.cpp" + }, + "59": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "60": { + "name": "storage.type.modifier.calling-convention.cpp" + }, + "61": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "62": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "63": { + "name": "comment.block.cpp" + }, + "64": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "65": { + "patterns": [ + { + "include": "#scope_resolution_function_definition_inner_generated" + } + ] + }, + "66": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.definition.cpp" + }, + "68": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "70": { + "name": "entity.name.function.definition.cpp" + }, + "71": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "72": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "73": { + "name": "comment.block.cpp" + }, + "74": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.function.definition.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.function.definition.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "contentName": "meta.function.definition.parameters.cpp", + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.section.parameters.begin.bracket.round.cpp" + } + }, + "end": "(\\))", "endCaptures": { - "0": { - "name": "punctuation.definition.scope.cpp" + "1": { + "name": "punctuation.section.parameters.end.bracket.round.cpp" } }, "patterns": [ { - "include": "#special_block" + "include": "#ever_present_context" }, { - "include": "#constructor" + "include": "#parameter_or_maybe_value" }, { - "include": "$base" + "include": "#comma" + }, + { + "include": "#evaluation_context" } ] }, { - "include": "$base" + "include": "#qualifiers_and_specifiers_post_parameters" + }, + { + "include": "$self" } ] }, { - "begin": "\\b(class|struct)\\b\\s*([_A-Za-z][_A-Za-z0-9]*\\b)?+(\\s*:\\s*(public|protected|private)\\s*([_A-Za-z][_A-Za-z0-9]*\\b)((\\s*,\\s*(public|protected|private)\\s*[_A-Za-z][_A-Za-z0-9]*\\b)*))?", + "name": "meta.body.function.definition.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.function.definition.cpp" + } + }, + "patterns": [ + { + "include": "#function_body_context" + } + ] + }, + { + "name": "meta.tail.function.definition.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "operator_overload": { + "name": "meta.function.definition.special.operator-overload.cpp", + "begin": "((?:(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<67>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<67>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<67>?)+)>)\\s*)?(?![\\w<:.]))(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<67>?)+)>)\\s*)?::)*)(operator)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<67>?)+)>)\\s*)?::)*)(?:(?:((?:\\+\\+|\\-\\-|\\(\\)|\\[\\]|\\->|\\+\\+|\\-\\-|\\+|\\-|!|~|\\*|&|new|new\\[\\]|delete|delete\\[\\]|\\->\\*|\\*|\\/|%|\\+|\\-|<<|>>|<=>|<|<=|>|>=|==|!=|&|\\^|\\||&&|\\|\\||=|\\+=|\\-=|\\*=|\\/=|%=|<<=|>>=|&=|\\^=|\\|=|,))|((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:\\[\\])?)))|(\"\")((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\<|\\())", + "beginCaptures": { + "1": { + "name": "meta.head.function.definition.special.operator-overload.cpp" + }, + "2": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "30": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "31": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "32": { + "name": "comment.block.cpp" + }, + "33": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "34": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "35": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "36": { + "name": "comment.block.cpp" + }, + "37": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "38": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "39": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "40": { + "name": "comment.block.cpp" + }, + "41": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "42": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "43": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "44": { + "name": "comment.block.cpp" + }, + "45": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "46": { + "name": "storage.type.modifier.calling-convention.cpp" + }, + "47": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "48": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "49": { + "name": "comment.block.cpp" + }, + "50": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "51": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "52": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "53": { + "name": "comment.block.cpp" + }, + "54": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "55": { + "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.operator.cpp" + }, + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "entity.name.operator.type.reference.cpp" + } + ] + }, + "71": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "72": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "73": { + "name": "comment.block.cpp" + }, + "74": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "75": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "76": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "77": { + "name": "comment.block.cpp" + }, + "78": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "79": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "80": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "81": { + "name": "comment.block.cpp" + }, + "82": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "83": { + "name": "entity.name.operator.type.array.cpp" + }, + "84": { + "name": "entity.name.operator.custom-literal.cpp" + }, + "85": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "86": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "87": { + "name": "comment.block.cpp" + }, + "88": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "89": { + "name": "entity.name.operator.custom-literal.cpp" + }, + "90": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "91": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "92": { + "name": "comment.block.cpp" + }, + "93": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.function.definition.special.operator-overload.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.function.definition.special.operator-overload.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#template_call_range" + }, + { + "contentName": "meta.function.definition.parameters.special.operator-overload.cpp", + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.section.parameters.begin.bracket.round.special.operator-overload.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parameters.end.bracket.round.special.operator-overload.cpp" + } + }, + "patterns": [ + { + "include": "#function_parameter_context" + }, + { + "include": "#evaluation_context" + } + ] + }, + { + "include": "#qualifiers_and_specifiers_post_parameters" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.body.function.definition.special.operator-overload.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.function.definition.special.operator-overload.cpp" + } + }, + "patterns": [ + { + "include": "#function_body_context" + } + ] + }, + { + "name": "meta.tail.function.definition.special.operator-overload.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "static_assert": { + "begin": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "keyword.other.static_assert.cpp" + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "10": { + "name": "punctuation.section.arguments.begin.bracket.round.static_assert.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.static_assert.cpp" + } + }, + "patterns": [ + { + "name": "meta.static_assert.message.cpp", + "begin": "(,)\\s*(?=(?:L|u8|u|U\\s*\\\")?)", "beginCaptures": { "1": { - "name": "storage.type.cpp" + "name": "punctuation.separator.delimiter.comma.cpp" + } + }, + "end": "(?=\\))", + "patterns": [ + { + "include": "#string_context" + }, + { + "include": "#string_context_c" + } + ] + }, + { + "include": "#evaluation_context" + } + ] + }, + "function_call": { + "begin": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<12>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(((?(?:(?>[^<>]*)\\g<12>?)+)>)\\s*)?(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution_function_call_inner_generated" + } + ] + }, + "2": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.call.cpp" + }, + "4": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "6": { + "name": "entity.name.function.call.cpp" + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "13": { + "name": "punctuation.section.arguments.begin.bracket.round.function.call.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.function.call.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "curly_initializer": { + "name": "meta.initialization.cpp", + "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(?![\\w<:.]))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\{)", + "beginCaptures": { + "1": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "storage.type.primitive.cpp storage.type.built-in.primitive.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "name": "storage.type.cpp storage.type.built-in.cpp" + }, + "15": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "16": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "17": { + "name": "comment.block.cpp" + }, + "18": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "19": { + "name": "support.type.posix-reserved.pthread.cpp support.type.built-in.posix-reserved.pthread.cpp" + }, + "20": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "21": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "22": { + "name": "comment.block.cpp" + }, + "23": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "24": { + "name": "support.type.posix-reserved.cpp support.type.built-in.posix-reserved.cpp" + }, + "25": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "26": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "27": { + "name": "comment.block.cpp" + }, + "28": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "29": { + "name": "punctuation.section.arguments.begin.bracket.round.initializer.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.initializer.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "constructor_inline": { + "name": "meta.function.definition.special.constructor.cpp", + "begin": "(^((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:(?:inline|constexpr|mutable|friend|explicit|virtual)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?|\\?\\?>)|(?=[;>\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.function.definition.special.constructor.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.function.definition.special.constructor.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "patterns": [ + { + "match": "(\\=)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(default)|(delete))", + "captures": { + "1": { + "name": "keyword.operator.assignment.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "keyword.other.default.constructor.cpp" + }, + "7": { + "name": "keyword.other.delete.constructor.cpp" + } + } + } + ] + }, + { + "include": "#functional_specifiers_pre_parameters" + }, + { + "begin": "(:)", + "beginCaptures": { + "1": { + "name": "punctuation.separator.initializers.cpp" + } + }, + "end": "(?=\\{)", + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "contentName": "meta.parameter.initialization.cpp", + "begin": "((?(?:(?>[^<>]*)\\g<3>?)+)>)\\s*)?(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.call.initializer.cpp" + }, + "2": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "4": { + "name": "punctuation.section.arguments.begin.bracket.round.function.call.initializer.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.function.call.initializer.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#evaluation_context" + } + ] + }, + { + "contentName": "meta.parameter.initialization.cpp", + "begin": "((?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.function.definition.special.constructor.cpp" + } + }, + "patterns": [ + { + "include": "#function_body_context" + } + ] + }, + { + "name": "meta.tail.function.definition.special.constructor.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "constructor_root": { + "name": "meta.function.definition.special.constructor.cpp", + "begin": "(\\s*+((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<14>?)+)>)\\s*)?::)*)(((?>(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))::((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))\\16((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\()))", + "beginCaptures": { + "1": { + "name": "meta.head.function.definition.special.constructor.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "storage.type.modifier.calling-convention.cpp" + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.constructor.cpp" + }, + { + "match": "(?|\\?\\?>)|(?=[;>\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.function.definition.special.constructor.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.function.definition.special.constructor.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "patterns": [ + { + "match": "(\\=)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(default)|(delete))", + "captures": { + "1": { + "name": "keyword.operator.assignment.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "keyword.other.default.constructor.cpp" + }, + "7": { + "name": "keyword.other.delete.constructor.cpp" + } + } + } + ] + }, + { + "include": "#functional_specifiers_pre_parameters" + }, + { + "begin": "(:)", + "beginCaptures": { + "1": { + "name": "punctuation.separator.initializers.cpp" + } + }, + "end": "(?=\\{)", + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "contentName": "meta.parameter.initialization.cpp", + "begin": "((?(?:(?>[^<>]*)\\g<3>?)+)>)\\s*)?(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.call.initializer.cpp" + }, + "2": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "4": { + "name": "punctuation.section.arguments.begin.bracket.round.function.call.initializer.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.function.call.initializer.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#evaluation_context" + } + ] + }, + { + "contentName": "meta.parameter.initialization.cpp", + "begin": "((?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.function.definition.special.constructor.cpp" + } + }, + "patterns": [ + { + "include": "#function_body_context" + } + ] + }, + { + "name": "meta.tail.function.definition.special.constructor.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "destructor_inline": { + "name": "meta.function.definition.special.member.destructor.cpp", + "begin": "(^((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:(?:inline|constexpr|mutable|friend|explicit|virtual)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*)(~(?|\\?\\?>)|(?=[;>\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.function.definition.special.member.destructor.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.function.definition.special.member.destructor.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "patterns": [ + { + "match": "(\\=)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(default)|(delete))", + "captures": { + "1": { + "name": "keyword.operator.assignment.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "keyword.other.default.constructor.cpp" + }, + "7": { + "name": "keyword.other.delete.constructor.cpp" + } + } + } + ] + }, + { + "contentName": "meta.function.definition.parameters.special.member.destructor.cpp", + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.section.parameters.begin.bracket.round.special.member.destructor.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parameters.end.bracket.round.special.member.destructor.cpp" + } + } + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.body.function.definition.special.member.destructor.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.function.definition.special.member.destructor.cpp" + } + }, + "patterns": [ + { + "include": "#function_body_context" + } + ] + }, + { + "name": "meta.tail.function.definition.special.member.destructor.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "destructor_root": { + "name": "meta.function.definition.special.member.destructor.cpp", + "begin": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<14>?)+)>)\\s*)?::)*)(((?>(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))::((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))~\\16((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\()))", + "beginCaptures": { + "1": { + "name": "meta.head.function.definition.special.member.destructor.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "storage.type.modifier.calling-convention.cpp" + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.destructor.cpp" + }, + { + "match": "(?|\\?\\?>)|(?=[;>\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.function.definition.special.member.destructor.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.function.definition.special.member.destructor.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "patterns": [ + { + "match": "(\\=)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(default)|(delete))", + "captures": { + "1": { + "name": "keyword.operator.assignment.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "keyword.other.default.constructor.cpp" + }, + "7": { + "name": "keyword.other.delete.constructor.cpp" + } + } + } + ] + }, + { + "contentName": "meta.function.definition.parameters.special.member.destructor.cpp", + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.section.parameters.begin.bracket.round.special.member.destructor.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parameters.end.bracket.round.special.member.destructor.cpp" + } + } + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.body.function.definition.special.member.destructor.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.function.definition.special.member.destructor.cpp" + } + }, + "patterns": [ + { + "include": "#function_body_context" + } + ] + }, + { + "name": "meta.tail.function.definition.special.member.destructor.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "operators": { + "patterns": [ + { + "include": "#sizeof_operator" + }, + { + "include": "#alignof_operator" + }, + { + "include": "#alignas_operator" + }, + { + "include": "#typeid_operator" + }, + { + "include": "#noexcept_operator" + }, + { + "match": "--", + "name": "keyword.operator.decrement.cpp" + }, + { + "match": "\\+\\+", + "name": "keyword.operator.increment.cpp" + }, + { + "match": "%=|\\+=|-=|\\*=|(?>=|\\|=", + "name": "keyword.operator.assignment.compound.bitwise.cpp" + }, + { + "match": "<<|>>", + "name": "keyword.operator.bitwise.shift.cpp" + }, + { + "match": "!=|<=|>=|==|<|>", + "name": "keyword.operator.comparison.cpp" + }, + { + "match": "&&|!|\\|\\|", + "name": "keyword.operator.logical.cpp" + }, + { + "match": "&|\\||\\^|~", + "name": "keyword.operator.cpp" + }, + { + "include": "#assignment_operator" + }, + { + "match": "%|\\*|\\/|-|\\+", + "name": "keyword.operator.cpp" + }, + { + "include": "#ternary_operator" + } + ] + }, + "wordlike_operators": { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "name": "keyword.operator.functionlike.cpp keyword.operator.sizeof.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.operator.sizeof.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.operator.sizeof.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "alignof_operator": { + "contentName": "meta.arguments.operator.alignof.cpp", + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "name": "keyword.operator.functionlike.cpp keyword.operator.alignof.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.operator.alignof.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.operator.alignof.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "alignas_operator": { + "contentName": "meta.arguments.operator.alignas.cpp", + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "name": "keyword.operator.functionlike.cpp keyword.operator.alignas.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.operator.alignas.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.operator.alignas.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "typeid_operator": { + "contentName": "meta.arguments.operator.typeid.cpp", + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "name": "keyword.operator.functionlike.cpp keyword.operator.typeid.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.operator.typeid.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.operator.typeid.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "noexcept_operator": { + "contentName": "meta.arguments.operator.noexcept.cpp", + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "name": "keyword.operator.functionlike.cpp keyword.operator.noexcept.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.operator.noexcept.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.operator.noexcept.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "ternary_operator": { + "applyEndPatternLast": true, + "begin": "(\\?)", + "beginCaptures": { + "1": { + "name": "keyword.operator.ternary.cpp" + } + }, + "end": "(:)", + "endCaptures": { + "1": { + "name": "keyword.operator.ternary.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#string_context" + }, + { + "include": "#number_literal" + }, + { + "include": "#string_context_c" + }, + { + "include": "#method_access" + }, + { + "include": "#member_access" + }, + { + "include": "#predefined_macros" + }, + { + "include": "#operators" + }, + { + "include": "#memory_operators" + }, + { + "include": "#wordlike_operators" + }, + { + "include": "#type_casting_operators" + }, + { + "include": "#control_flow_keywords" + }, + { + "include": "#exception_keywords" + }, + { + "include": "#the_this_keyword" + }, + { + "include": "#language_constants" + }, + { + "include": "#builtin_storage_type_initilizer" + }, + { + "include": "#storage_types" + }, + { + "include": "#qualifiers_and_specifiers_post_parameters" + }, + { + "include": "#functional_specifiers_pre_parameters" + }, + { + "include": "#misc_storage_modifiers" + }, + { + "include": "#lambdas" + }, + { + "include": "#attributes_context" + }, + { + "include": "#parentheses" + }, + { + "include": "#function_call" + }, + { + "include": "#scope_resolution_inner_generated" + }, + { + "include": "#square_brackets" + }, + { + "include": "#empty_square_brackets" + }, + { + "include": "#semicolon" + }, + { + "include": "#comma" + } + ] + }, + "function_pointer": { + "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(?![\\w<:.]))(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()(\\*)\\s*((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)\\s*(?:(\\[)(\\w*)(\\])\\s*)*(\\))\\s*(\\()", + "beginCaptures": { + "1": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "29": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "30": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "31": { + "name": "comment.block.cpp" + }, + "32": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "33": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "34": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "35": { + "name": "comment.block.cpp" + }, + "36": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "37": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "38": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "39": { + "name": "comment.block.cpp" + }, + "40": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "41": { + "name": "punctuation.section.parens.begin.bracket.round.function.pointer.cpp" + }, + "42": { + "name": "punctuation.definition.function.pointer.dereference.cpp" + }, + "43": { + "name": "variable.other.definition.pointer.function.cpp" + }, + "44": { + "name": "punctuation.definition.begin.bracket.square.cpp" + }, + "45": { + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "46": { + "name": "punctuation.definition.end.bracket.square.cpp" + }, + "47": { + "name": "punctuation.section.parens.end.bracket.round.function.pointer.cpp" + }, + "48": { + "name": "punctuation.section.parameters.begin.bracket.round.function.pointer.cpp" + } + }, + "end": "(\\))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=[{=,);]|\\n)(?!\\()", + "endCaptures": { + "1": { + "name": "punctuation.section.parameters.end.bracket.round.function.pointer.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "patterns": [ + { + "include": "#function_parameter_context" + } + ] + }, + "function_pointer_parameter": { + "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(?![\\w<:.]))(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()(\\*)\\s*((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)\\s*(?:(\\[)(\\w*)(\\])\\s*)*(\\))\\s*(\\()", + "beginCaptures": { + "1": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "29": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "30": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "31": { + "name": "comment.block.cpp" + }, + "32": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "33": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "34": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "35": { + "name": "comment.block.cpp" + }, + "36": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "37": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "38": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "39": { + "name": "comment.block.cpp" + }, + "40": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "41": { + "name": "punctuation.section.parens.begin.bracket.round.function.pointer.cpp" + }, + "42": { + "name": "punctuation.definition.function.pointer.dereference.cpp" + }, + "43": { + "name": "variable.parameter.pointer.function.cpp" + }, + "44": { + "name": "punctuation.definition.begin.bracket.square.cpp" + }, + "45": { + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "46": { + "name": "punctuation.definition.end.bracket.square.cpp" + }, + "47": { + "name": "punctuation.section.parens.end.bracket.round.function.pointer.cpp" + }, + "48": { + "name": "punctuation.section.parameters.begin.bracket.round.function.pointer.cpp" + } + }, + "end": "(\\))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=[{=,);]|\\n)(?!\\()", + "endCaptures": { + "1": { + "name": "punctuation.section.parameters.end.bracket.round.function.pointer.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "patterns": [ + { + "include": "#function_parameter_context" + } + ] + }, + "typedef_function_pointer": { + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(?![\\w<:.]))(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()(\\*)\\s*((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)\\s*(?:(\\[)(\\w*)(\\])\\s*)*(\\))\\s*(\\()", + "beginCaptures": { + "1": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?|\\[|\\]|=))", - "name": "meta.class-struct-block.cpp", - "patterns": [ - { - "include": "#angle_brackets" }, - { - "begin": "\\{", - "beginCaptures": { - "0": { - "name": "punctuation.section.block.begin.bracket.curly.cpp" - } - }, - "end": "(\\})(\\s*\\n)?", - "endCaptures": { - "1": { - "name": "punctuation.section.block.end.bracket.curly.cpp" - }, - "2": { - "name": "invalid.illegal.you-forgot-semicolon.cpp" - } - }, + "7": { "patterns": [ { - "include": "#special_block" - }, - { - "include": "#constructor" - }, - { - "include": "$base" + "include": "#inline_comment" } ] }, - { - "include": "$base" + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "12": { + "patterns": [ + { + "include": "#scope_resolution_inner_generated" + } + ] + }, + "13": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, + "15": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "17": { + "name": "entity.name.scope-resolution.cpp" + }, + "18": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "20": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, + "21": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "22": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "23": { + "name": "comment.block.cpp" + }, + "24": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "25": { + "name": "entity.name.type.cpp" + }, + "26": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "28": { + "patterns": [ + { + "match": "\\*", + "name": "storage.modifier.pointer.cpp" + }, + { + "match": "(?:\\&((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "29": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "30": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "31": { + "name": "comment.block.cpp" + }, + "32": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "33": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "34": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "35": { + "name": "comment.block.cpp" + }, + "36": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "37": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "38": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "39": { + "name": "comment.block.cpp" + }, + "40": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "41": { + "name": "punctuation.section.parens.begin.bracket.round.function.pointer.cpp" + }, + "42": { + "name": "punctuation.definition.function.pointer.dereference.cpp" + }, + "43": { + "name": "entity.name.type.alias.cpp entity.name.type.pointer.function.cpp" + }, + "44": { + "name": "punctuation.definition.begin.bracket.square.cpp" + }, + "45": { + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "46": { + "name": "punctuation.definition.end.bracket.square.cpp" + }, + "47": { + "name": "punctuation.section.parens.end.bracket.round.function.pointer.cpp" + }, + "48": { + "name": "punctuation.section.parameters.begin.bracket.round.function.pointer.cpp" } - ] - }, - { - "begin": "\\b(extern)(?=\\s*\")", - "beginCaptures": { + }, + "end": "(\\))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=[{=,);]|\\n)(?!\\()", + "endCaptures": { "1": { - "name": "storage.modifier.cpp" - } - }, - "end": "(?<=\\})|(?=\\w)|(?=\\s*#\\s*endif\\b)", - "name": "meta.extern-block.cpp", - "patterns": [ - { - "begin": "\\{", - "beginCaptures": { - "0": { - "name": "punctuation.section.block.begin.bracket.curly.c" - } - }, - "end": "\\}|(?=\\s*#\\s*endif\\b)", - "endCaptures": { - "0": { - "name": "punctuation.section.block.end.bracket.curly.c" - } - }, + "name": "punctuation.section.parameters.end.bracket.round.function.pointer.cpp" + }, + "2": { "patterns": [ { - "include": "#special_block" - }, - { - "include": "$base" + "include": "#inline_comment" } ] }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "patterns": [ { - "include": "$base" + "include": "#function_parameter_context" } ] } ] }, - "strings": { + "parameter_or_maybe_value": { + "name": "meta.parameter.cpp", + "begin": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\w)", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "end": "(?:(?=\\))|(,))", + "endCaptures": { + "1": { + "name": "punctuation.separator.delimiter.comma.cpp" + } + }, "patterns": [ { - "begin": "(u|u8|U|L)?\"", + "include": "#ever_present_context" + }, + { + "include": "#function_pointer_parameter" + }, + { + "include": "#memory_operators" + }, + { + "include": "#builtin_storage_type_initilizer" + }, + { + "include": "#curly_initializer" + }, + { + "include": "#decltype" + }, + { + "include": "#vararg_ellipses" + }, + { + "match": "((?:((?:const|static|volatile|register|restrict|extern))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))+)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=,|\\)|=)", + "captures": { + "1": { + "patterns": [ + { + "include": "#storage_types" + } + ] + }, + "2": { + "name": "storage.modifier.specifier.parameter.cpp" + }, + "3": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "4": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "5": { + "name": "comment.block.cpp" + }, + "6": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "12": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "13": { + "name": "comment.block.cpp" + }, + "14": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "15": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "16": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "17": { + "name": "comment.block.cpp" + }, + "18": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "19": { + "name": "storage.type.primitive.cpp storage.type.built-in.primitive.cpp" + }, + "20": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "21": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "22": { + "name": "comment.block.cpp" + }, + "23": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "24": { + "name": "storage.type.cpp storage.type.built-in.cpp" + }, + "25": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "26": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "27": { + "name": "comment.block.cpp" + }, + "28": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "29": { + "name": "support.type.posix-reserved.pthread.cpp support.type.built-in.posix-reserved.pthread.cpp" + }, + "30": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "31": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "32": { + "name": "comment.block.cpp" + }, + "33": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "34": { + "name": "support.type.posix-reserved.cpp support.type.built-in.posix-reserved.cpp" + }, + "35": { + "name": "entity.name.type.parameter.cpp" + }, + "36": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "37": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "38": { + "name": "comment.block.cpp" + }, + "39": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + { + "include": "#storage_types" + }, + { + "include": "#function_call" + }, + { + "include": "#scope_resolution_parameter_inner_generated" + }, + { + "match": "(?:class|struct|union|enum)", + "name": "storage.type.$0.cpp" + }, + { + "begin": "(?<==)", + "end": "(?:(?=\\))|(,))", + "endCaptures": { + "1": { + "name": "punctuation.separator.delimiter.comma.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\)|,|\\[|=|\\n)", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "variable.parameter.cpp" + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + { + "include": "#attributes_context" + }, + { + "name": "meta.bracket.square.array.cpp", + "begin": "(\\[)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.begin.bracket.square.array.type.cpp" + } + }, + "end": "(\\])", + "endCaptures": { + "1": { + "name": "punctuation.definition.end.bracket.square.array.type.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + { + "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*)", + "captures": { + "0": { + "patterns": [ + { + "match": "\\*", + "name": "storage.modifier.pointer.cpp" + }, + { + "match": "(?:\\&((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + { + "include": "#evaluation_context" + } + ] + }, + "parameter": { + "name": "meta.parameter.cpp", + "begin": "((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\w)", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "end": "(?:(?=\\))|(,))", + "endCaptures": { + "1": { + "name": "punctuation.separator.delimiter.comma.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#function_pointer_parameter" + }, + { + "include": "#decltype" + }, + { + "include": "#vararg_ellipses" + }, + { + "match": "((?:((?:const|static|volatile|register|restrict|extern))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))+)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=,|\\)|=)", + "captures": { + "1": { + "patterns": [ + { + "include": "#storage_types" + } + ] + }, + "2": { + "name": "storage.modifier.specifier.parameter.cpp" + }, + "3": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "4": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "5": { + "name": "comment.block.cpp" + }, + "6": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "12": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "13": { + "name": "comment.block.cpp" + }, + "14": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "15": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "16": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "17": { + "name": "comment.block.cpp" + }, + "18": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "19": { + "name": "storage.type.primitive.cpp storage.type.built-in.primitive.cpp" + }, + "20": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "21": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "22": { + "name": "comment.block.cpp" + }, + "23": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "24": { + "name": "storage.type.cpp storage.type.built-in.cpp" + }, + "25": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "26": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "27": { + "name": "comment.block.cpp" + }, + "28": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "29": { + "name": "support.type.posix-reserved.pthread.cpp support.type.built-in.posix-reserved.pthread.cpp" + }, + "30": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "31": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "32": { + "name": "comment.block.cpp" + }, + "33": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "34": { + "name": "support.type.posix-reserved.cpp support.type.built-in.posix-reserved.cpp" + }, + "35": { + "name": "entity.name.type.parameter.cpp" + }, + "36": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "37": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "38": { + "name": "comment.block.cpp" + }, + "39": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + { + "include": "#storage_types" + }, + { + "include": "#scope_resolution_parameter_inner_generated" + }, + { + "match": "(?:class|struct|union|enum)", + "name": "storage.type.$0.cpp" + }, + { + "begin": "(?<==)", + "end": "(?:(?=\\))|(,))", + "endCaptures": { + "1": { + "name": "punctuation.separator.delimiter.comma.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + { + "include": "#assignment_operator" + }, + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\)|,|\\[|=|\\n)", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "variable.parameter.cpp" + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + { + "include": "#attributes_context" + }, + { + "name": "meta.bracket.square.array.cpp", + "begin": "(\\[)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.begin.bracket.square.array.type.cpp" + } + }, + "end": "(\\])", + "endCaptures": { + "1": { + "name": "punctuation.definition.end.bracket.square.array.type.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + { + "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*)", + "captures": { + "0": { + "patterns": [ + { + "match": "\\*", + "name": "storage.modifier.pointer.cpp" + }, + { + "match": "(?:\\&((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + } + ] + }, + "member_access": { + "match": "(?:((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\*|->)))((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*(?:(?:(?:\\.\\*|\\.))|(?:(?:->\\*|->)))\\s*)*)\\s*(\\b(?!auto[^(?-mix:\\w)]|void[^(?-mix:\\w)]|char[^(?-mix:\\w)]|short[^(?-mix:\\w)]|int[^(?-mix:\\w)]|signed[^(?-mix:\\w)]|unsigned[^(?-mix:\\w)]|long[^(?-mix:\\w)]|float[^(?-mix:\\w)]|double[^(?-mix:\\w)]|bool[^(?-mix:\\w)]|wchar_t[^(?-mix:\\w)]|u_char[^(?-mix:\\w)]|u_short[^(?-mix:\\w)]|u_int[^(?-mix:\\w)]|u_long[^(?-mix:\\w)]|ushort[^(?-mix:\\w)]|uint[^(?-mix:\\w)]|u_quad_t[^(?-mix:\\w)]|quad_t[^(?-mix:\\w)]|qaddr_t[^(?-mix:\\w)]|caddr_t[^(?-mix:\\w)]|daddr_t[^(?-mix:\\w)]|div_t[^(?-mix:\\w)]|dev_t[^(?-mix:\\w)]|fixpt_t[^(?-mix:\\w)]|blkcnt_t[^(?-mix:\\w)]|blksize_t[^(?-mix:\\w)]|gid_t[^(?-mix:\\w)]|in_addr_t[^(?-mix:\\w)]|in_port_t[^(?-mix:\\w)]|ino_t[^(?-mix:\\w)]|key_t[^(?-mix:\\w)]|mode_t[^(?-mix:\\w)]|nlink_t[^(?-mix:\\w)]|id_t[^(?-mix:\\w)]|pid_t[^(?-mix:\\w)]|off_t[^(?-mix:\\w)]|segsz_t[^(?-mix:\\w)]|swblk_t[^(?-mix:\\w)]|uid_t[^(?-mix:\\w)]|id_t[^(?-mix:\\w)]|clock_t[^(?-mix:\\w)]|size_t[^(?-mix:\\w)]|ssize_t[^(?-mix:\\w)]|time_t[^(?-mix:\\w)]|useconds_t[^(?-mix:\\w)]|suseconds_t[^(?-mix:\\w)]|int8_t[^(?-mix:\\w)]|int16_t[^(?-mix:\\w)]|int32_t[^(?-mix:\\w)]|int64_t[^(?-mix:\\w)]|uint8_t[^(?-mix:\\w)]|uint16_t[^(?-mix:\\w)]|uint32_t[^(?-mix:\\w)]|uint64_t[^(?-mix:\\w)]|int_least8_t[^(?-mix:\\w)]|int_least16_t[^(?-mix:\\w)]|int_least32_t[^(?-mix:\\w)]|int_least64_t[^(?-mix:\\w)]|uint_least8_t[^(?-mix:\\w)]|uint_least16_t[^(?-mix:\\w)]|uint_least32_t[^(?-mix:\\w)]|uint_least64_t[^(?-mix:\\w)]|int_fast8_t[^(?-mix:\\w)]|int_fast16_t[^(?-mix:\\w)]|int_fast32_t[^(?-mix:\\w)]|int_fast64_t[^(?-mix:\\w)]|uint_fast8_t[^(?-mix:\\w)]|uint_fast16_t[^(?-mix:\\w)]|uint_fast32_t[^(?-mix:\\w)]|uint_fast64_t[^(?-mix:\\w)]|intptr_t[^(?-mix:\\w)]|uintptr_t[^(?-mix:\\w)]|intmax_t[^(?-mix:\\w)]|intmax_t[^(?-mix:\\w)]|uintmax_t[^(?-mix:\\w)]|uintmax_t[^(?-mix:\\w)])(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b(?!\\())", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "variable.language.this.cpp" + }, + "6": { + "name": "variable.other.object.access.cpp" + }, + "7": { + "name": "punctuation.separator.dot-access.cpp" + }, + "8": { + "name": "punctuation.separator.pointer-access.cpp" + }, + "9": { + "patterns": [ + { + "match": "(?<=(?:\\.\\*|\\.|->|->\\*))\\s*(?:((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\*|->)))", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "variable.language.this.cpp" + }, + "6": { + "name": "variable.other.object.property.cpp" + }, + "7": { + "name": "punctuation.separator.dot-access.cpp" + }, + "8": { + "name": "punctuation.separator.pointer-access.cpp" + } + } + }, + { + "match": "(?:((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\*|->)))", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "variable.language.this.cpp" + }, + "6": { + "name": "variable.other.object.access.cpp" + }, + "7": { + "name": "punctuation.separator.dot-access.cpp" + }, + "8": { + "name": "punctuation.separator.pointer-access.cpp" + } + } + }, + { + "include": "#member_access" + }, + { + "include": "#method_access" + } + ] + }, + "10": { + "name": "variable.other.property.cpp" + } + } + }, + "method_access": { + "begin": "(?:((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\*|->)))((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*(?:(?:(?:\\.\\*|\\.))|(?:(?:->\\*|->)))\\s*)*)\\s*(~?(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "variable.language.this.cpp" + }, + "6": { + "name": "variable.other.object.access.cpp" + }, + "7": { + "name": "punctuation.separator.dot-access.cpp" + }, + "8": { + "name": "punctuation.separator.pointer-access.cpp" + }, + "9": { + "patterns": [ + { + "match": "(?<=(?:\\.\\*|\\.|->|->\\*))\\s*(?:((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\*|->)))", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "variable.language.this.cpp" + }, + "6": { + "name": "variable.other.object.property.cpp" + }, + "7": { + "name": "punctuation.separator.dot-access.cpp" + }, + "8": { + "name": "punctuation.separator.pointer-access.cpp" + } + } + }, + { + "match": "(?:((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\*|->)))", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "variable.language.this.cpp" + }, + "6": { + "name": "variable.other.object.access.cpp" + }, + "7": { + "name": "punctuation.separator.dot-access.cpp" + }, + "8": { + "name": "punctuation.separator.pointer-access.cpp" + } + } + }, + { + "include": "#member_access" + }, + { + "include": "#method_access" + } + ] + }, + "10": { + "name": "entity.name.function.member.cpp" + }, + "11": { + "name": "punctuation.section.arguments.begin.bracket.round.function.member.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.function.member.cpp" + } + }, + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "using_namespace": { + "name": "meta.using-namespace.cpp", + "begin": "(?(?:(?>[^<>]*)\\g<7>?)+)>)\\s*)?::)*\\s*+)?((?(?:(?>[^<>]*)\\g<9>?)+)>)\\s*)?::)*\\s*+)\\s*((?|\\?\\?>)|(?=[;>\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.namespace.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.namespace.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#attributes_context" + }, + { + "match": "((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<5>?)+)>)\\s*)?::)*\\s*+)\\s*((?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.namespace.cpp" + } + }, + "patterns": [ + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.namespace.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "macro_argument": { + "match": "##?(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*(?!\\w)", + "name": "variable.other.macro.argument.cpp" + }, + "lambdas": { + "begin": "((?:(?<=[^\\s]|^)(?])|(?<=\\Wreturn|^return))\\s*(\\[(?!\\[))((?:[^\\]\\[]*\\[.*?\\](?!\\s*\\[)[^\\]\\[]*?)*[^\\]\\[]*?)(\\](?!\\[)))", + "beginCaptures": { + "2": { + "name": "punctuation.definition.capture.begin.lambda.cpp" + }, + "3": { + "name": "meta.lambda.capture.cpp", + "patterns": [ + { + "include": "#the_this_keyword" + }, + { + "match": "((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?=\\]|\\z|$)|(,))|(\\=))", + "captures": { + "1": { + "name": "variable.parameter.capture.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "punctuation.separator.delimiter.comma.cpp" + }, + "7": { + "name": "keyword.operator.assignment.cpp" + } + } + }, + { + "include": "#evaluation_context" + } + ] + }, + "4": { + "name": "punctuation.definition.capture.end.lambda.cpp" + } + }, + "end": "(?<=})", + "patterns": [ + { + "name": "meta.function.definition.parameters.lambda.cpp", + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.definition.parameters.begin.lambda.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.lambda.cpp" + } + }, + "patterns": [ + { + "include": "#function_parameter_context" + } + ] + }, + { + "match": "(?)((?:.+?(?=\\{|$))?)", + "captures": { + "1": { + "name": "punctuation.definition.lambda.return-type.cpp" + }, + "2": { + "name": "storage.type.return-type.lambda.cpp" + } + } + }, + { + "name": "meta.function.definition.body.lambda.cpp", + "begin": "(\\{)", + "beginCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.lambda.cpp" + } + }, + "end": "(\\})", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.lambda.cpp" + } + }, + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "enumerator_list": { + "match": "((?(?:(?>[^<>]*)\\g<15>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<15>?)+)>)\\s*)?(::))?\\s*((?|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.cpp" + }, + "2": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "patterns": [ + { + "name": "meta.head.enum.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.enum.cpp" + } + }, + "patterns": [ + { + "include": "$self" + } + ] + }, + { + "name": "meta.body.enum.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.enum.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#enumerator_list" + }, + { + "include": "#comma" + }, + { + "include": "#semicolon" + } + ] + }, + { + "name": "meta.tail.enum.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "inheritance_context": { + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.delimiter.comma.inheritance.cpp" + }, + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(?![\\w<:.]))", + "captures": { + "1": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.class.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.cpp" + }, + "2": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "patterns": [ + { + "name": "meta.head.class.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.class.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#inheritance_context" + }, + { + "include": "#template_call_range" + } + ] + }, + { + "name": "meta.body.class.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.class.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.class.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "struct_block": { + "name": "meta.block.struct.cpp", + "begin": "((((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.struct.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.cpp" + }, + "2": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "patterns": [ + { + "name": "meta.head.struct.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.struct.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#inheritance_context" + }, + { + "include": "#template_call_range" + } + ] + }, + { + "name": "meta.body.struct.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.struct.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.struct.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "union_block": { + "name": "meta.block.union.cpp", + "begin": "((((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.union.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.cpp" + }, + "2": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "patterns": [ + { + "name": "meta.head.union.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.union.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#inheritance_context" + }, + { + "include": "#template_call_range" + } + ] + }, + { + "name": "meta.body.union.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.union.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.union.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "extern_block": { + "name": "meta.block.extern.cpp", + "begin": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(extern)(?=\\s*\\\"))", + "beginCaptures": { + "1": { + "name": "meta.head.extern.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "storage.type.extern.cpp" + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.cpp" + }, + "2": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "patterns": [ + { + "name": "meta.head.extern.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.extern.cpp" + } + }, + "patterns": [ + { + "include": "$self" + } + ] + }, + { + "name": "meta.body.extern.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.extern.cpp" + } + }, + "patterns": [ + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.extern.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + }, + { + "include": "$self" + } + ] + }, + "typedef_class": { + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.class.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.cpp" + }, + "2": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "patterns": [ + { + "name": "meta.head.class.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.class.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#inheritance_context" + }, + { + "include": "#template_call_range" + } + ] + }, + { + "name": "meta.body.class.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.class.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.class.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "match": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "name": "entity.name.type.alias.cpp" + } + } + }, + { + "match": "," + } + ] + } + ] + } + ] + }, + "typedef_struct": { + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.struct.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.cpp" + }, + "2": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "patterns": [ + { + "name": "meta.head.struct.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.struct.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#inheritance_context" + }, + { + "include": "#template_call_range" + } + ] + }, + { + "name": "meta.body.struct.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.struct.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.struct.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "match": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "name": "entity.name.type.alias.cpp" + } + } + }, + { + "match": "," + } + ] + } + ] + } + ] + }, + "typedef_union": { + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.union.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.cpp" + }, + "2": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "patterns": [ + { + "name": "meta.head.union.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.union.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#inheritance_context" + }, + { + "include": "#template_call_range" + } + ] + }, + { + "name": "meta.body.union.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.union.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.union.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "match": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "name": "entity.name.type.alias.cpp" + } + } + }, + { + "match": "," + } + ] + } + ] + } + ] + }, + "struct_declare": { + "match": "(struct)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))\\b(?!final\\W|final\\$|override\\W|override\\$)((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\S)(?!:)", + "captures": { + "1": { + "name": "storage.type.struct.declare.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "entity.name.type.struct.cpp" + }, + "7": { + "patterns": [ + { + "match": "\\*", + "name": "storage.modifier.pointer.cpp" + }, + { + "match": "(?:\\&((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "8": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "9": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "10": { + "name": "comment.block.cpp" + }, + "11": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "12": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "13": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "14": { + "name": "comment.block.cpp" + }, + "15": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "16": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "17": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "18": { + "name": "comment.block.cpp" + }, + "19": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "20": { + "name": "variable.other.object.declare.cpp" + }, + "21": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "22": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "23": { + "name": "comment.block.cpp" + }, + "24": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + "union_declare": { + "match": "(union)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))\\b(?!final\\W|final\\$|override\\W|override\\$)((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\S)(?!:)", + "captures": { + "1": { + "name": "storage.type.union.declare.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "entity.name.type.union.cpp" + }, + "7": { + "patterns": [ + { + "match": "\\*", + "name": "storage.modifier.pointer.cpp" + }, + { + "match": "(?:\\&((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "8": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "9": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "10": { + "name": "comment.block.cpp" + }, + "11": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "12": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "13": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "14": { + "name": "comment.block.cpp" + }, + "15": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "16": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "17": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "18": { + "name": "comment.block.cpp" + }, + "19": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "20": { + "name": "variable.other.object.declare.cpp" + }, + "21": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "22": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "23": { + "name": "comment.block.cpp" + }, + "24": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + "enum_declare": { + "match": "(enum)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))\\b(?!final\\W|final\\$|override\\W|override\\$)((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\S)(?!:)", + "captures": { + "1": { + "name": "storage.type.enum.declare.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "entity.name.type.enum.cpp" + }, + "7": { + "patterns": [ + { + "match": "\\*", + "name": "storage.modifier.pointer.cpp" + }, + { + "match": "(?:\\&((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "8": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "9": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "10": { + "name": "comment.block.cpp" + }, + "11": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "12": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "13": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "14": { + "name": "comment.block.cpp" + }, + "15": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "16": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "17": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "18": { + "name": "comment.block.cpp" + }, + "19": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "20": { + "name": "variable.other.object.declare.cpp" + }, + "21": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "22": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "23": { + "name": "comment.block.cpp" + }, + "24": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + "class_declare": { + "match": "(class)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))\\b(?!final\\W|final\\$|override\\W|override\\$)((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\S)(?!:)", + "captures": { + "1": { + "name": "storage.type.class.declare.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "entity.name.type.class.cpp" + }, + "7": { + "patterns": [ + { + "match": "\\*", + "name": "storage.modifier.pointer.cpp" + }, + { + "match": "(?:\\&((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "8": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "9": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "10": { + "name": "comment.block.cpp" + }, + "11": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "12": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "13": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "14": { + "name": "comment.block.cpp" + }, + "15": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "16": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "17": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "18": { + "name": "comment.block.cpp" + }, + "19": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "20": { + "name": "variable.other.object.declare.cpp" + }, + "21": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "22": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "23": { + "name": "comment.block.cpp" + }, + "24": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + "standard_declares": { + "patterns": [ + { + "include": "#struct_declare" + }, + { + "include": "#union_declare" + }, + { + "include": "#enum_declare" + }, + { + "include": "#class_declare" + } + ] + }, + "parameter_struct": { + "match": "(struct)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:\\[((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))\\]((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?(?=,|\\)|\\n)", + "captures": { + "1": { + "name": "storage.type.struct.parameter.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "entity.name.type.struct.parameter.cpp" + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "patterns": [ + { + "match": "\\*", + "name": "storage.modifier.pointer.cpp" + }, + { + "match": "(?:\\&((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "12": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "13": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "14": { + "name": "comment.block.cpp" + }, + "15": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "16": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "17": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "18": { + "name": "comment.block.cpp" + }, + "19": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "20": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "21": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "22": { + "name": "comment.block.cpp" + }, + "23": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "24": { + "name": "variable.other.object.declare.cpp" + }, + "25": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "26": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "27": { + "name": "comment.block.cpp" + }, + "28": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "29": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "30": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "31": { + "name": "comment.block.cpp" + }, + "32": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "33": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "34": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "35": { + "name": "comment.block.cpp" + }, + "36": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + "parameter_enum": { + "match": "(enum)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:\\[((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))\\]((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?(?=,|\\)|\\n)", + "captures": { + "1": { + "name": "storage.type.enum.parameter.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "entity.name.type.enum.parameter.cpp" + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "patterns": [ + { + "match": "\\*", + "name": "storage.modifier.pointer.cpp" + }, + { + "match": "(?:\\&((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "12": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "13": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "14": { + "name": "comment.block.cpp" + }, + "15": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "16": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "17": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "18": { + "name": "comment.block.cpp" + }, + "19": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "20": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "21": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "22": { + "name": "comment.block.cpp" + }, + "23": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "24": { + "name": "variable.other.object.declare.cpp" + }, + "25": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "26": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "27": { + "name": "comment.block.cpp" + }, + "28": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "29": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "30": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "31": { + "name": "comment.block.cpp" + }, + "32": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "33": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "34": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "35": { + "name": "comment.block.cpp" + }, + "36": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + "parameter_union": { + "match": "(union)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:\\[((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))\\]((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?(?=,|\\)|\\n)", + "captures": { + "1": { + "name": "storage.type.union.parameter.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "entity.name.type.union.parameter.cpp" + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "patterns": [ + { + "match": "\\*", + "name": "storage.modifier.pointer.cpp" + }, + { + "match": "(?:\\&((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "12": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "13": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "14": { + "name": "comment.block.cpp" + }, + "15": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "16": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "17": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "18": { + "name": "comment.block.cpp" + }, + "19": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "20": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "21": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "22": { + "name": "comment.block.cpp" + }, + "23": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "24": { + "name": "variable.other.object.declare.cpp" + }, + "25": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "26": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "27": { + "name": "comment.block.cpp" + }, + "28": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "29": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "30": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "31": { + "name": "comment.block.cpp" + }, + "32": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "33": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "34": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "35": { + "name": "comment.block.cpp" + }, + "36": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + "parameter_class": { + "match": "(class)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:\\[((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))\\]((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?(?=,|\\)|\\n)", + "captures": { + "1": { + "name": "storage.type.class.parameter.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "entity.name.type.class.parameter.cpp" + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "patterns": [ + { + "match": "\\*", + "name": "storage.modifier.pointer.cpp" + }, + { + "match": "(?:\\&((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "12": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "13": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "14": { + "name": "comment.block.cpp" + }, + "15": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "16": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "17": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "18": { + "name": "comment.block.cpp" + }, + "19": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "20": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "21": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "22": { + "name": "comment.block.cpp" + }, + "23": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "24": { + "name": "variable.other.object.declare.cpp" + }, + "25": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "26": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "27": { + "name": "comment.block.cpp" + }, + "28": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "29": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "30": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "31": { + "name": "comment.block.cpp" + }, + "32": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "33": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "34": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "35": { + "name": "comment.block.cpp" + }, + "36": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + }, + "over_qualified_types": { + "patterns": [ + { + "include": "#parameter_struct" + }, + { + "include": "#parameter_enum" + }, + { + "include": "#parameter_union" + }, + { + "include": "#parameter_class" + } + ] + }, + "hacky_fix_for_stray_directive": { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))#define.*(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((#)\\s*define\\b)\\s+((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)(?:(\\()([^()\\\\]+)(\\)))?", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "keyword.control.directive.define.cpp" + }, + "6": { + "name": "punctuation.definition.directive.cpp" + }, + "7": { + "name": "entity.name.function.preprocessor.cpp" + }, + "8": { + "name": "punctuation.definition.parameters.begin.cpp" + }, + "9": { + "patterns": [ + { + "match": "(?<=[(,])\\s*((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*", + "captures": { + "1": { + "name": "variable.parameter.preprocessor.cpp" + } + } + }, + { + "match": ",", + "name": "punctuation.separator.parameters.cpp" + }, + { + "match": "\\.\\.\\.", + "name": "punctuation.vararg-ellipses.variable.parameter.preprocessor.cpp" + } + ] + }, + "10": { + "name": "punctuation.definition.parameters.end.cpp" + } + }, + "end": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((#)\\s*((?:(?:include|include_next)|import))\\b)\\s*(?:(?:(?:((<)[^>]*(>?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:\\n|$)|(?=\\/\\/)))|((\\\")[^\\\"]*(\\\"?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:\\n|$)|(?=\\/\\/))))|((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:\\n|$)|(?=\\/\\/))))|((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:\\n|$)|(?=\\/\\/)))", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "keyword.control.directive.$7.cpp" + }, + "6": { + "name": "punctuation.definition.directive.cpp" + }, + "8": { + "name": "string.quoted.other.lt-gt.include.cpp" + }, + "9": { + "name": "punctuation.definition.string.begin.cpp" + }, + "10": { + "name": "punctuation.definition.string.end.cpp" + }, + "11": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "12": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "13": { + "name": "comment.block.cpp" + }, + "14": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "15": { + "name": "string.quoted.double.include.cpp" + }, + "16": { + "name": "punctuation.definition.string.begin.cpp" + }, + "17": { + "name": "punctuation.definition.string.end.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "19": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "20": { + "name": "comment.block.cpp" + }, + "21": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "22": { + "name": "entity.name.other.preprocessor.macro.include.cpp" + }, + "23": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "24": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "25": { + "name": "comment.block.cpp" + }, + "26": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "27": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "28": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "29": { + "name": "comment.block.cpp" + }, + "30": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "meta.preprocessor.include.cpp" + }, + "meta_preprocessor_line": { + "name": "meta.preprocessor.cpp", + "begin": "^\\s*((#)\\s*line)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.line.cpp" + }, + "2": { + "name": "punctuation.definition.directive.cpp" + } + }, + "end": "(?=(?://|/\\*))|(?=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", + "end": "(?<=\\))(?!\\w)|(?=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.cpp" + }, + "2": { + "name": "punctuation.section.arguments.begin.bracket.round.cpp" + } + }, + "end": "(\\))|(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<14>?)+)>)\\s*)?::)*)(((?>(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))::((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))\\16((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\()))", + "beginCaptures": { + "1": { + "name": "meta.head.function.definition.special.constructor.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "storage.type.modifier.calling-convention.cpp" + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.constructor.cpp" + }, + { + "match": "(?|\\?\\?>)|(?=[;>\\[\\]=]))|(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(default)|(delete))", + "captures": { + "1": { + "name": "keyword.operator.assignment.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "keyword.other.default.constructor.cpp" + }, + "7": { + "name": "keyword.other.delete.constructor.cpp" + } + } + } + ] + }, + { + "include": "#functional_specifiers_pre_parameters" + }, + { + "begin": "(:)", + "beginCaptures": { + "1": { + "name": "punctuation.separator.initializers.cpp" + } + }, + "end": "(?=\\{)", + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "contentName": "meta.parameter.initialization.cpp", + "begin": "((?(?:(?>[^<>]*)\\g<3>?)+)>)\\s*)?(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.call.initializer.cpp" + }, + "2": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "4": { + "name": "punctuation.section.arguments.begin.bracket.round.function.call.initializer.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.function.call.initializer.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#evaluation_context" + } + ] + }, + { + "contentName": "meta.parameter.initialization.cpp", + "begin": "((?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.function.definition.special.constructor.cpp" + } + }, + "patterns": [ + { + "include": "#function_body_context" + } + ] + }, + { + "name": "meta.tail.function.definition.special.constructor.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "macro_safe_destructor_root": { + "name": "meta.function.definition.special.member.destructor.cpp", + "begin": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<14>?)+)>)\\s*)?::)*)(((?>(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))::((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))~\\16((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\()))", + "beginCaptures": { + "1": { + "name": "meta.head.function.definition.special.member.destructor.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "storage.type.modifier.calling-convention.cpp" + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.destructor.cpp" + }, + { + "match": "(?|\\?\\?>)|(?=[;>\\[\\]=]))|(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(default)|(delete))", + "captures": { + "1": { + "name": "keyword.operator.assignment.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "keyword.other.default.constructor.cpp" + }, + "7": { + "name": "keyword.other.delete.constructor.cpp" + } + } + } + ] + }, + { + "contentName": "meta.function.definition.parameters.special.member.destructor.cpp", + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.section.parameters.begin.bracket.round.special.member.destructor.cpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parameters.end.bracket.round.special.member.destructor.cpp" + } + } + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.body.function.definition.special.member.destructor.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.function.definition.special.member.destructor.cpp" + } + }, + "patterns": [ + { + "include": "#function_body_context" + } + ] + }, + { + "name": "meta.tail.function.definition.special.member.destructor.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "macro_safe_function_definition": { + "name": "meta.function.definition.cpp", + "begin": "((?:(?:^|\\G|(?<=;|\\}))|(?<=>))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?(?:((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<69>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<69>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<69>?)+)>)\\s*)?(?![\\w<:.]))(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<69>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\())", + "beginCaptures": { + "1": { + "name": "meta.head.function.definition.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "storage.type.template.cpp" + }, + "7": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "8": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "9": { + "name": "comment.block.cpp" + }, + "10": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "11": { + "name": "storage.modifier.$11.cpp" + }, + "12": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "13": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "14": { + "name": "comment.block.cpp" + }, + "15": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "16": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "44": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "45": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "46": { + "name": "comment.block.cpp" + }, + "47": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "48": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "49": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "50": { + "name": "comment.block.cpp" + }, + "51": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "52": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "53": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "54": { + "name": "comment.block.cpp" + }, + "55": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "56": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "57": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "58": { + "name": "comment.block.cpp" + }, + "59": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "60": { + "name": "storage.type.modifier.calling-convention.cpp" + }, + "61": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "62": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "63": { + "name": "comment.block.cpp" + }, + "64": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "65": { + "patterns": [ + { + "include": "#scope_resolution_function_definition_inner_generated" + } + ] + }, + "66": { + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.definition.cpp" + }, + "68": { + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_range" + } + ] + }, + "70": { + "name": "entity.name.function.definition.cpp" + }, + "71": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "72": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "73": { + "name": "comment.block.cpp" + }, + "74": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))|(?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.function.definition.cpp" + } + }, + "patterns": [ + { + "include": "#function_body_context" + } + ] + }, + { + "name": "meta.tail.function.definition.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "macro_safe_operator_overload": { + "name": "meta.function.definition.special.operator-overload.cpp", + "begin": "((?:(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<67>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<67>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<67>?)+)>)\\s*)?(?![\\w<:.]))(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<67>?)+)>)\\s*)?::)*)(operator)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<67>?)+)>)\\s*)?::)*)(?:(?:((?:\\+\\+|\\-\\-|\\(\\)|\\[\\]|\\->|\\+\\+|\\-\\-|\\+|\\-|!|~|\\*|&|new|new\\[\\]|delete|delete\\[\\]|\\->\\*|\\*|\\/|%|\\+|\\-|<<|>>|<=>|<|<=|>|>=|==|!=|&|\\^|\\||&&|\\|\\||=|\\+=|\\-=|\\*=|\\/=|%=|<<=|>>=|&=|\\^=|\\|=|,))|((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?:\\[\\])?)))|(\"\")((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=\\<|\\())", + "beginCaptures": { + "1": { + "name": "meta.head.function.definition.special.operator-overload.cpp" + }, + "2": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "30": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "31": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "32": { + "name": "comment.block.cpp" + }, + "33": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "34": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "35": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "36": { + "name": "comment.block.cpp" + }, + "37": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "38": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "39": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "40": { + "name": "comment.block.cpp" + }, + "41": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "42": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "43": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "44": { + "name": "comment.block.cpp" + }, + "45": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "46": { + "name": "storage.type.modifier.calling-convention.cpp" + }, + "47": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "48": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "49": { + "name": "comment.block.cpp" + }, + "50": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "51": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "52": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "53": { + "name": "comment.block.cpp" + }, + "54": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "55": { + "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.operator.cpp" + }, + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "entity.name.operator.type.reference.cpp" + } + ] + }, + "71": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "72": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "73": { + "name": "comment.block.cpp" + }, + "74": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "75": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "76": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "77": { + "name": "comment.block.cpp" + }, + "78": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "79": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "80": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "81": { + "name": "comment.block.cpp" + }, + "82": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "83": { + "name": "entity.name.operator.type.array.cpp" + }, + "84": { + "name": "entity.name.operator.custom-literal.cpp" + }, + "85": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "86": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "87": { + "name": "comment.block.cpp" + }, + "88": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "89": { + "name": "entity.name.operator.custom-literal.cpp" + }, + "90": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "91": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "92": { + "name": "comment.block.cpp" + }, + "93": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))|(?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.function.definition.special.operator-overload.cpp" + } + }, + "patterns": [ + { + "include": "#function_body_context" + } + ] + }, + { + "name": "meta.tail.function.definition.special.operator-overload.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "macro_safe_using_namespace": { + "name": "meta.using-namespace.cpp", + "begin": "(?(?:(?>[^<>]*)\\g<7>?)+)>)\\s*)?::)*\\s*+)?((?|\\?\\?>)|(?=[;>\\[\\]=]))|(?(?:(?>[^<>]*)\\g<5>?)+)>)\\s*)?::)*\\s*+)\\s*((?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.namespace.cpp" + } + }, + "patterns": [ + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.namespace.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "macro_safe_extern_block": { + "name": "meta.block.extern.cpp", + "begin": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(extern)(?=\\s*\\\"))", + "beginCaptures": { + "1": { + "name": "meta.head.extern.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "name": "storage.type.extern.cpp" + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))|(?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.extern.cpp" + } + }, + "patterns": [ + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.extern.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + }, + { + "include": "$self" + } + ] + }, + "macro_safe_typedef_class": { + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.class.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.cpp" + }, + "2": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "patterns": [ + { + "name": "meta.head.class.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.class.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#inheritance_context" + }, + { + "include": "#template_call_range" + } + ] + }, + { + "name": "meta.body.class.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.class.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.class.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "match": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "name": "entity.name.type.alias.cpp" + } + } + }, + { + "match": "," + } + ] + } + ] + } + ] + }, + "macro_safe_typedef_struct": { + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.struct.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.cpp" + }, + "2": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "patterns": [ + { + "name": "meta.head.struct.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.struct.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#inheritance_context" + }, + { + "include": "#template_call_range" + } + ] + }, + { + "name": "meta.body.struct.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.struct.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.struct.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "match": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "name": "entity.name.type.alias.cpp" + } + } + }, + { + "match": "," + } + ] + } + ] + } + ] + }, + "macro_safe_typedef_union": { + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.union.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.cpp" + }, + "2": { + "name": "punctuation.terminator.statement.cpp" + } + }, + "patterns": [ + { + "name": "meta.head.union.cpp", + "begin": "\\G ?", + "end": "((?:\\{|<%|\\?\\?<|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.union.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#inheritance_context" + }, + { + "include": "#template_call_range" + } + ] + }, + { + "name": "meta.body.union.cpp", + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "(\\}|%>|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.union.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.union.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "match": "(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "name": "entity.name.type.alias.cpp" + } + } + }, + { + "match": "," + } + ] + } + ] + } + ] + }, + "macro_safe_typedef_function_pointer": { + "begin": "((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(?![\\w<:.]))(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()(\\*)\\s*((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)\\s*(?:(\\[)(\\w*)(\\])\\s*)*(\\))\\s*(\\()", + "beginCaptures": { + "1": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "29": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "30": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "31": { + "name": "comment.block.cpp" + }, + "32": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "33": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "34": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "35": { + "name": "comment.block.cpp" + }, + "36": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "37": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "38": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "39": { + "name": "comment.block.cpp" + }, + "40": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "41": { + "name": "punctuation.section.parens.begin.bracket.round.function.pointer.cpp" + }, + "42": { + "name": "punctuation.definition.function.pointer.dereference.cpp" + }, + "43": { + "name": "entity.name.type.alias.cpp entity.name.type.pointer.function.cpp" + }, + "44": { + "name": "punctuation.definition.begin.bracket.square.cpp" + }, + "45": { + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "46": { + "name": "punctuation.definition.end.bracket.square.cpp" + }, + "47": { + "name": "punctuation.section.parens.end.bracket.round.function.pointer.cpp" + }, + "48": { + "name": "punctuation.section.parameters.begin.bracket.round.function.pointer.cpp" + } + }, + "end": "(\\))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=[{=,);]|\\n)(?!\\()", + "endCaptures": { + "1": { + "name": "punctuation.section.parameters.end.bracket.round.function.pointer.cpp" + }, + "2": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "3": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "4": { + "name": "comment.block.cpp" + }, + "5": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "patterns": [ + { + "include": "#function_parameter_context" + } + ] + } + ] + }, + "macro_safe_class_block": { + "name": "meta.block.class.cpp", + "begin": "((((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.class.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))|(?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.class.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.class.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "macro_safe_struct_block": { + "name": "meta.block.struct.cpp", + "begin": "((((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.struct.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))|(?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.struct.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.struct.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "macro_safe_union_block": { + "name": "meta.block.union.cpp", + "begin": "((((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(DLLEXPORT)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?\\s*((?:(?\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:(?:(?:::)?(?:(?:(?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?::)*\\s*+)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?:::))?(?:(?:(?:(?>\\s+)|(?:\\/\\*)(?:(?>(?:[^\\*]|(?>\\*+)[^\\/])*)(?:(?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)(?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?:(?:(?(?:(?>[^<>]*)?)+)>)\\s*)?(?![\\w<:.])))+)*))?))", + "beginCaptures": { + "1": { + "name": "meta.head.union.cpp" + }, + "3": { + "name": "storage.type.$3.cpp" + }, + "4": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "5": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "6": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "7": { + "name": "comment.block.cpp" + }, + "8": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "9": { + "name": "entity.name.other.preprocessor.macro.predefined.DLLEXPORT.cpp" + }, + "10": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "11": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "12": { + "name": "comment.block.cpp" + }, + "13": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "14": { + "patterns": [ + { + "include": "#attributes_context" + }, + { + "include": "#number_literal" + } + ] + }, + "15": { + "name": "entity.name.type.$3.cpp" + }, + "16": { + "name": "storage.type.modifier.final.cpp" + }, + "17": { + "name": "punctuation.separator.colon.inheritance.cpp" + }, + "18": { + "patterns": [ + { + "include": "#inheritance_context" + } + ] + } + }, + "end": "(?:(?:(?<=\\}|%>|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))|(?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.union.cpp" + } + }, + "patterns": [ + { + "include": "#function_pointer" + }, + { + "include": "#static_assert" + }, + { + "include": "#constructor_inline" + }, + { + "include": "#destructor_inline" + }, + { + "include": "$self" + } + ] + }, + { + "name": "meta.tail.union.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "macro_safe_enum_block": { + "name": "meta.block.enum.cpp", + "begin": "(((?(?:(?>[^<>]*)\\g<15>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<15>?)+)>)\\s*)?(::))?\\s*((?|\\?\\?>)\\s*(;)|(;))|(?=[;>\\[\\]=]))|(?|\\?\\?>)", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.enum.cpp" + } + }, + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#enumerator_list" + }, + { + "include": "#comma" + }, + { + "include": "#semicolon" + } + ] + }, + { + "name": "meta.tail.enum.cpp", + "begin": "(?<=\\}|%>|\\?\\?>)[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "macro_safe_template_definition": { + "name": "meta.template.definition.cpp", + "begin": "(?)|(?)", + "endCaptures": { + "1": { + "name": "punctuation.section.angle-brackets.begin.template.call.cpp" + } + }, + "patterns": [ + { + "include": "#template_call_context" + } + ] + }, + { + "include": "#template_definition_context" + } + ] + }, + "macro_safe_block": { + "name": "meta.block.cpp", + "begin": "({)", + "beginCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.cpp" + } + }, + "end": "(}|(?=\\s*#\\s*(?:elif|else|endif)\\b))|(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))((?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "5": { + "name": "keyword.other.static_assert.cpp" + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "10": { + "name": "punctuation.section.arguments.begin.bracket.round.static_assert.cpp" + } + }, + "end": "(\\))|(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?:(?:(?:short|signed|unsigned|long)|(?:class|struct|union|enum))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(((::)?(?:((?-mix:(?!\\b(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|class|struct|union|enum|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(::))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?!(?:not|compl|sizeof|new|delete|not_eq|bitand|xor|bitor|and|or|throw|and_eq|xor_eq|or_eq|alignof|alignas|typeid|noexcept|noexcept|static_cast|dynamic_cast|const_cast|reinterpret_cast|while|for|do|if|else|goto|switch|try|catch|return|break|case|continue|default|NULL|true|false|nullptr|const|static|volatile|register|restrict|extern|inline|constexpr|mutable|friend|explicit|virtual|final|override|volatile|const|noexcept|constexpr|mutable|constexpr|consteval|private|protected|public|if|elif|else|endif|ifdef|ifndef|define|undef|include|line|error|warning|pragma|_Pragma|defined|__has_include|__has_cpp_attribute|this|template|namespace|using|operator|typedef|decltype|typename|asm|__asm__|concept|requires|export|thread_local|atomic_cancel|atomic_commit|atomic_noexcept|co_await|co_return|co_yield|import|module|reflexpr|synchronized|audit|axiom|transaction_safe|transaction_safe_dynamic)\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?(?:(?>[^<>]*)\\g<27>?)+)>)\\s*)?(?![\\w<:.]))(((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))?(?:(?:\\&|\\*)((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))*(?:\\&|\\*))?((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(\\()(\\*)\\s*((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)\\s*(?:(\\[)(\\w*)(\\])\\s*)*(\\))\\s*(\\()", + "beginCaptures": { + "1": { + "name": "meta.qualified_type.cpp", + "patterns": [ + { + "match": "(?\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))){2,}\\&", + "captures": { + "1": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + }, + "name": "invalid.illegal.reference-type.cpp" + }, + { + "match": "\\&", + "name": "storage.modifier.reference.cpp" + } + ] + }, + "29": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "30": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "31": { + "name": "comment.block.cpp" + }, + "32": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "33": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "34": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "35": { + "name": "comment.block.cpp" + }, + "36": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "37": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "38": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "39": { + "name": "comment.block.cpp" + }, + "40": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + }, + "41": { + "name": "punctuation.section.parens.begin.bracket.round.function.pointer.cpp" + }, + "42": { + "name": "punctuation.definition.function.pointer.dereference.cpp" + }, + "43": { + "name": "variable.other.definition.pointer.function.cpp" + }, + "44": { + "name": "punctuation.definition.begin.bracket.square.cpp" + }, + "45": { + "patterns": [ + { + "include": "#evaluation_context" + } + ] + }, + "46": { + "name": "punctuation.definition.end.bracket.square.cpp" + }, + "47": { + "name": "punctuation.section.parens.end.bracket.round.function.pointer.cpp" + }, + "48": { + "name": "punctuation.section.parameters.begin.bracket.round.function.pointer.cpp" + } + }, + "end": "(\\))((?:(?:(?>\\s+)|(\\/\\*)((?>(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+?|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z)))(?=[{=,);]|\\n)(?!\\()|(? using namespace std; +#define EXTERN_C extern "C" + class Rectangle { int width, height; public: @@ -18,5 +20,8 @@ int main () { Rectangle rect; rect.set_values (3,4); cout << "area: " << rect.area(); + Task::links_to; + int t = 2; + if (t > 0) puts("\n*************************************************"); return 0; } \ No newline at end of file diff --git a/extensions/cpp/test/colorize-results/test-23630_cpp.json b/extensions/cpp/test/colorize-results/test-23630_cpp.json index f22786a105f..a58961ae945 100644 --- a/extensions/cpp/test/colorize-results/test-23630_cpp.json +++ b/extensions/cpp/test/colorize-results/test-23630_cpp.json @@ -1,7 +1,7 @@ [ { "c": "#", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c punctuation.definition.directive.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp punctuation.definition.directive.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -12,7 +12,7 @@ }, { "c": "ifndef", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -23,7 +23,7 @@ }, { "c": " ", - "t": "source.cpp meta.preprocessor.c", + "t": "source.cpp meta.preprocessor.cpp", "r": { "dark_plus": "meta.preprocessor: #569CD6", "light_plus": "meta.preprocessor: #0000FF", @@ -34,7 +34,7 @@ }, { "c": "_UCRT", - "t": "source.cpp meta.preprocessor.c entity.name.function.preprocessor.c", + "t": "source.cpp meta.preprocessor.cpp entity.name.function.preprocessor.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -45,7 +45,7 @@ }, { "c": " ", - "t": "source.cpp meta.preprocessor.macro.c", + "t": "source.cpp meta.preprocessor.macro.cpp", "r": { "dark_plus": "meta.preprocessor: #569CD6", "light_plus": "meta.preprocessor: #0000FF", @@ -56,7 +56,7 @@ }, { "c": "#", - "t": "source.cpp meta.preprocessor.macro.c keyword.control.directive.define.c punctuation.definition.directive.c", + "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp punctuation.definition.directive.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -67,7 +67,7 @@ }, { "c": "define", - "t": "source.cpp meta.preprocessor.macro.c keyword.control.directive.define.c", + "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -78,7 +78,7 @@ }, { "c": " ", - "t": "source.cpp meta.preprocessor.macro.c", + "t": "source.cpp meta.preprocessor.macro.cpp", "r": { "dark_plus": "meta.preprocessor: #569CD6", "light_plus": "meta.preprocessor: #0000FF", @@ -89,7 +89,7 @@ }, { "c": "_UCRT", - "t": "source.cpp meta.preprocessor.macro.c entity.name.function.preprocessor.c", + "t": "source.cpp meta.preprocessor.macro.cpp entity.name.function.preprocessor.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -100,7 +100,7 @@ }, { "c": "#", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c punctuation.definition.directive.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp punctuation.definition.directive.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -111,7 +111,7 @@ }, { "c": "endif", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", diff --git a/extensions/cpp/test/colorize-results/test-23850_cpp.json b/extensions/cpp/test/colorize-results/test-23850_cpp.json index bbb5237498f..924bbc78243 100644 --- a/extensions/cpp/test/colorize-results/test-23850_cpp.json +++ b/extensions/cpp/test/colorize-results/test-23850_cpp.json @@ -1,7 +1,7 @@ [ { "c": "#", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c punctuation.definition.directive.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp punctuation.definition.directive.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -12,7 +12,7 @@ }, { "c": "ifndef", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -23,7 +23,7 @@ }, { "c": " ", - "t": "source.cpp meta.preprocessor.c", + "t": "source.cpp meta.preprocessor.cpp", "r": { "dark_plus": "meta.preprocessor: #569CD6", "light_plus": "meta.preprocessor: #0000FF", @@ -34,7 +34,7 @@ }, { "c": "_UCRT", - "t": "source.cpp meta.preprocessor.c entity.name.function.preprocessor.c", + "t": "source.cpp meta.preprocessor.cpp entity.name.function.preprocessor.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -45,7 +45,7 @@ }, { "c": "#", - "t": "source.cpp meta.preprocessor.macro.c keyword.control.directive.define.c punctuation.definition.directive.c", + "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp punctuation.definition.directive.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -56,7 +56,7 @@ }, { "c": "define", - "t": "source.cpp meta.preprocessor.macro.c keyword.control.directive.define.c", + "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -67,7 +67,7 @@ }, { "c": " ", - "t": "source.cpp meta.preprocessor.macro.c", + "t": "source.cpp meta.preprocessor.macro.cpp", "r": { "dark_plus": "meta.preprocessor: #569CD6", "light_plus": "meta.preprocessor: #0000FF", @@ -78,7 +78,7 @@ }, { "c": "_UCRT", - "t": "source.cpp meta.preprocessor.macro.c entity.name.function.preprocessor.c", + "t": "source.cpp meta.preprocessor.macro.cpp entity.name.function.preprocessor.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -89,7 +89,7 @@ }, { "c": "#", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c punctuation.definition.directive.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp punctuation.definition.directive.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -100,7 +100,7 @@ }, { "c": "endif", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", diff --git a/extensions/cpp/test/colorize-results/test_c.json b/extensions/cpp/test/colorize-results/test_c.json index 0725010d8c2..74be734c5ca 100644 --- a/extensions/cpp/test/colorize-results/test_c.json +++ b/extensions/cpp/test/colorize-results/test_c.json @@ -243,7 +243,7 @@ }, { "c": "int", - "t": "source.c storage.type.c", + "t": "source.c storage.type.built-in.primitive.c", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -265,7 +265,7 @@ }, { "c": "main", - "t": "source.c meta.function.c entity.name.function.c", + "t": "source.c meta.function.c meta.function.definition.parameters.c entity.name.function.c", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -276,7 +276,7 @@ }, { "c": "(", - "t": "source.c meta.function.c punctuation.section.parameters.begin.bracket.round.c", + "t": "source.c meta.function.c meta.function.definition.parameters.c punctuation.section.parameters.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -287,7 +287,7 @@ }, { "c": ")", - "t": "source.c meta.function.c punctuation.section.parameters.end.bracket.round.c", + "t": "source.c meta.function.c meta.function.definition.parameters.c punctuation.section.parameters.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -320,7 +320,7 @@ }, { "c": "float", - "t": "source.c meta.block.c storage.type.c", + "t": "source.c meta.block.c storage.type.built-in.primitive.c", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -507,7 +507,7 @@ }, { "c": " ", - "t": "source.c meta.block.c punctuation.whitespace.support.function.leading.c", + "t": "source.c meta.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -518,18 +518,18 @@ }, { "c": "printf", - "t": "source.c meta.block.c support.function.C99.c", + "t": "source.c meta.block.c meta.function-call.c entity.name.function.c", "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" + "hc_black": "entity.name.function: #DCDCAA" } }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -540,7 +540,7 @@ }, { "c": "\"", - "t": "source.c meta.block.c string.quoted.double.c punctuation.definition.string.begin.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c punctuation.definition.string.begin.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -551,7 +551,7 @@ }, { "c": "Enter coefficients a, b and c: ", - "t": "source.c meta.block.c string.quoted.double.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -562,7 +562,7 @@ }, { "c": "\"", - "t": "source.c meta.block.c string.quoted.double.c punctuation.definition.string.end.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c punctuation.definition.string.end.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -573,7 +573,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -595,7 +595,7 @@ }, { "c": " ", - "t": "source.c meta.block.c punctuation.whitespace.support.function.leading.c", + "t": "source.c meta.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -606,18 +606,18 @@ }, { "c": "scanf", - "t": "source.c meta.block.c support.function.C99.c", + "t": "source.c meta.block.c meta.function-call.c entity.name.function.c", "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" + "hc_black": "entity.name.function: #DCDCAA" } }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -628,7 +628,7 @@ }, { "c": "\"", - "t": "source.c meta.block.c string.quoted.double.c punctuation.definition.string.begin.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c punctuation.definition.string.begin.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -639,7 +639,7 @@ }, { "c": "%f%f%f", - "t": "source.c meta.block.c string.quoted.double.c constant.other.placeholder.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c constant.other.placeholder.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -650,7 +650,7 @@ }, { "c": "\"", - "t": "source.c meta.block.c string.quoted.double.c punctuation.definition.string.end.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c punctuation.definition.string.end.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -661,7 +661,7 @@ }, { "c": ",", - "t": "source.c meta.block.c punctuation.separator.delimiter.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.separator.delimiter.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -672,7 +672,7 @@ }, { "c": "&", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.function-call.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -683,7 +683,7 @@ }, { "c": "a", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -694,7 +694,7 @@ }, { "c": ",", - "t": "source.c meta.block.c punctuation.separator.delimiter.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.separator.delimiter.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -705,7 +705,7 @@ }, { "c": "&", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.function-call.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -716,7 +716,7 @@ }, { "c": "b", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -727,7 +727,7 @@ }, { "c": ",", - "t": "source.c meta.block.c punctuation.separator.delimiter.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.separator.delimiter.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -738,7 +738,7 @@ }, { "c": "&", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.function-call.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -749,7 +749,7 @@ }, { "c": "c", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -760,7 +760,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -848,7 +848,7 @@ }, { "c": "4", - "t": "source.c meta.block.c constant.numeric.c", + "t": "source.c meta.block.c constant.numeric.decimal.c", "r": { "dark_plus": "constant.numeric: #B5CEA8", "light_plus": "constant.numeric: #09885A", @@ -947,7 +947,7 @@ }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -958,7 +958,7 @@ }, { "c": "determinant", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.parens.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -969,7 +969,7 @@ }, { "c": ">", - "t": "source.c meta.block.c keyword.operator.comparison.c", + "t": "source.c meta.block.c meta.parens.block.c keyword.operator.comparison.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -980,7 +980,7 @@ }, { "c": "0", - "t": "source.c meta.block.c constant.numeric.c", + "t": "source.c meta.block.c meta.parens.block.c constant.numeric.decimal.c", "r": { "dark_plus": "constant.numeric: #B5CEA8", "light_plus": "constant.numeric: #09885A", @@ -991,7 +991,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1057,7 +1057,7 @@ }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1068,7 +1068,7 @@ }, { "c": "-", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.parens.block.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1079,7 +1079,7 @@ }, { "c": "b", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.parens.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1090,7 +1090,7 @@ }, { "c": "+", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.parens.block.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1101,18 +1101,18 @@ }, { "c": "sqrt", - "t": "source.c meta.block.c support.function.C99.c", + "t": "source.c meta.block.c meta.parens.block.c meta.function-call.c entity.name.function.c", "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" + "hc_black": "entity.name.function: #DCDCAA" } }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1123,7 +1123,7 @@ }, { "c": "determinant", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.parens.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1133,8 +1133,19 @@ } }, { - "c": "))", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "c": ")", + "t": "source.c meta.block.c meta.parens.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ")", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1156,7 +1167,7 @@ }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1167,7 +1178,7 @@ }, { "c": "2", - "t": "source.c meta.block.c constant.numeric.c", + "t": "source.c meta.block.c meta.parens.block.c constant.numeric.decimal.c", "r": { "dark_plus": "constant.numeric: #B5CEA8", "light_plus": "constant.numeric: #09885A", @@ -1178,7 +1189,7 @@ }, { "c": "*", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.parens.block.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1189,7 +1200,7 @@ }, { "c": "a", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.parens.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1200,7 +1211,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1255,7 +1266,7 @@ }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1266,7 +1277,7 @@ }, { "c": "-", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.parens.block.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1277,7 +1288,7 @@ }, { "c": "b", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.parens.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1288,7 +1299,7 @@ }, { "c": "-", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.parens.block.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1299,18 +1310,18 @@ }, { "c": "sqrt", - "t": "source.c meta.block.c support.function.C99.c", + "t": "source.c meta.block.c meta.parens.block.c meta.function-call.c entity.name.function.c", "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" + "hc_black": "entity.name.function: #DCDCAA" } }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1321,7 +1332,7 @@ }, { "c": "determinant", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.parens.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1331,8 +1342,19 @@ } }, { - "c": "))", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "c": ")", + "t": "source.c meta.block.c meta.parens.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ")", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1354,7 +1376,7 @@ }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1365,7 +1387,7 @@ }, { "c": "2", - "t": "source.c meta.block.c constant.numeric.c", + "t": "source.c meta.block.c meta.parens.block.c constant.numeric.decimal.c", "r": { "dark_plus": "constant.numeric: #B5CEA8", "light_plus": "constant.numeric: #09885A", @@ -1376,7 +1398,7 @@ }, { "c": "*", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.parens.block.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1387,7 +1409,7 @@ }, { "c": "a", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.parens.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1398,7 +1420,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1420,7 +1442,7 @@ }, { "c": " ", - "t": "source.c meta.block.c punctuation.whitespace.support.function.leading.c", + "t": "source.c meta.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1431,18 +1453,18 @@ }, { "c": "printf", - "t": "source.c meta.block.c support.function.C99.c", + "t": "source.c meta.block.c meta.function-call.c entity.name.function.c", "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" + "hc_black": "entity.name.function: #DCDCAA" } }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1453,7 +1475,7 @@ }, { "c": "\"", - "t": "source.c meta.block.c string.quoted.double.c punctuation.definition.string.begin.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c punctuation.definition.string.begin.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1464,7 +1486,7 @@ }, { "c": "Roots are: ", - "t": "source.c meta.block.c string.quoted.double.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1475,7 +1497,7 @@ }, { "c": "%.2f", - "t": "source.c meta.block.c string.quoted.double.c constant.other.placeholder.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c constant.other.placeholder.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1486,7 +1508,7 @@ }, { "c": " and ", - "t": "source.c meta.block.c string.quoted.double.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1497,7 +1519,7 @@ }, { "c": "%.2f", - "t": "source.c meta.block.c string.quoted.double.c constant.other.placeholder.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c constant.other.placeholder.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1508,7 +1530,7 @@ }, { "c": "\"", - "t": "source.c meta.block.c string.quoted.double.c punctuation.definition.string.end.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c punctuation.definition.string.end.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1519,7 +1541,7 @@ }, { "c": ",", - "t": "source.c meta.block.c punctuation.separator.delimiter.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.separator.delimiter.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1530,7 +1552,7 @@ }, { "c": "r1 ", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1541,7 +1563,7 @@ }, { "c": ",", - "t": "source.c meta.block.c punctuation.separator.delimiter.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.separator.delimiter.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1552,7 +1574,7 @@ }, { "c": " r2", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1563,7 +1585,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1662,7 +1684,7 @@ }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1673,7 +1695,7 @@ }, { "c": "determinant", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.parens.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1684,7 +1706,7 @@ }, { "c": "==", - "t": "source.c meta.block.c keyword.operator.comparison.c", + "t": "source.c meta.block.c meta.parens.block.c keyword.operator.comparison.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1695,7 +1717,7 @@ }, { "c": "0", - "t": "source.c meta.block.c constant.numeric.c", + "t": "source.c meta.block.c meta.parens.block.c constant.numeric.decimal.c", "r": { "dark_plus": "constant.numeric: #B5CEA8", "light_plus": "constant.numeric: #09885A", @@ -1706,7 +1728,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1827,7 +1849,7 @@ }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1838,7 +1860,7 @@ }, { "c": "2", - "t": "source.c meta.block.c constant.numeric.c", + "t": "source.c meta.block.c meta.parens.block.c constant.numeric.decimal.c", "r": { "dark_plus": "constant.numeric: #B5CEA8", "light_plus": "constant.numeric: #09885A", @@ -1849,7 +1871,7 @@ }, { "c": "*", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.parens.block.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1860,7 +1882,7 @@ }, { "c": "a", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.parens.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1871,7 +1893,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1893,7 +1915,7 @@ }, { "c": " ", - "t": "source.c meta.block.c punctuation.whitespace.support.function.leading.c", + "t": "source.c meta.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1904,18 +1926,18 @@ }, { "c": "printf", - "t": "source.c meta.block.c support.function.C99.c", + "t": "source.c meta.block.c meta.function-call.c entity.name.function.c", "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" + "hc_black": "entity.name.function: #DCDCAA" } }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1926,7 +1948,7 @@ }, { "c": "\"", - "t": "source.c meta.block.c string.quoted.double.c punctuation.definition.string.begin.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c punctuation.definition.string.begin.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1937,7 +1959,7 @@ }, { "c": "Roots are: ", - "t": "source.c meta.block.c string.quoted.double.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1948,7 +1970,7 @@ }, { "c": "%.2f", - "t": "source.c meta.block.c string.quoted.double.c constant.other.placeholder.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c constant.other.placeholder.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1959,7 +1981,7 @@ }, { "c": " and ", - "t": "source.c meta.block.c string.quoted.double.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1970,7 +1992,7 @@ }, { "c": "%.2f", - "t": "source.c meta.block.c string.quoted.double.c constant.other.placeholder.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c constant.other.placeholder.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1981,7 +2003,7 @@ }, { "c": "\"", - "t": "source.c meta.block.c string.quoted.double.c punctuation.definition.string.end.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c punctuation.definition.string.end.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1992,7 +2014,7 @@ }, { "c": ",", - "t": "source.c meta.block.c punctuation.separator.delimiter.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.separator.delimiter.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2003,7 +2025,7 @@ }, { "c": " r1", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2014,7 +2036,7 @@ }, { "c": ",", - "t": "source.c meta.block.c punctuation.separator.delimiter.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.separator.delimiter.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2025,7 +2047,7 @@ }, { "c": " r2", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2036,7 +2058,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2190,7 +2212,7 @@ }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2201,7 +2223,7 @@ }, { "c": "2", - "t": "source.c meta.block.c constant.numeric.c", + "t": "source.c meta.block.c meta.parens.block.c constant.numeric.decimal.c", "r": { "dark_plus": "constant.numeric: #B5CEA8", "light_plus": "constant.numeric: #09885A", @@ -2212,7 +2234,7 @@ }, { "c": "*", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.parens.block.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -2223,7 +2245,7 @@ }, { "c": "a", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.parens.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2234,7 +2256,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2278,50 +2300,6 @@ }, { "c": " ", - "t": "source.c meta.block.c punctuation.whitespace.support.function.leading.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "sqrt", - "t": "source.c meta.block.c support.function.C99.c", - "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" - } - }, - { - "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "-", - "t": "source.c meta.block.c keyword.operator.c", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": "determinant", "t": "source.c meta.block.c", "r": { "dark_plus": "default: #D4D4D4", @@ -2331,9 +2309,53 @@ "hc_black": "default: #FFFFFF" } }, + { + "c": "sqrt", + "t": "source.c meta.block.c meta.function-call.c entity.name.function.c", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": "(", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "-", + "t": "source.c meta.block.c meta.function-call.c keyword.operator.c", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": "determinant", + "t": "source.c meta.block.c meta.function-call.c", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2355,7 +2377,7 @@ }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2366,7 +2388,7 @@ }, { "c": "2", - "t": "source.c meta.block.c constant.numeric.c", + "t": "source.c meta.block.c meta.parens.block.c constant.numeric.decimal.c", "r": { "dark_plus": "constant.numeric: #B5CEA8", "light_plus": "constant.numeric: #09885A", @@ -2377,7 +2399,7 @@ }, { "c": "*", - "t": "source.c meta.block.c keyword.operator.c", + "t": "source.c meta.block.c meta.parens.block.c keyword.operator.c", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -2388,7 +2410,7 @@ }, { "c": "a", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.parens.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2399,7 +2421,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.parens.block.c punctuation.section.parens.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2421,7 +2443,7 @@ }, { "c": " ", - "t": "source.c meta.block.c punctuation.whitespace.support.function.leading.c", + "t": "source.c meta.block.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2432,18 +2454,18 @@ }, { "c": "printf", - "t": "source.c meta.block.c support.function.C99.c", + "t": "source.c meta.block.c meta.function-call.c entity.name.function.c", "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" + "hc_black": "entity.name.function: #DCDCAA" } }, { "c": "(", - "t": "source.c meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2454,7 +2476,7 @@ }, { "c": "\"", - "t": "source.c meta.block.c string.quoted.double.c punctuation.definition.string.begin.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c punctuation.definition.string.begin.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2465,7 +2487,7 @@ }, { "c": "Roots are: ", - "t": "source.c meta.block.c string.quoted.double.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2476,7 +2498,7 @@ }, { "c": "%.2f", - "t": "source.c meta.block.c string.quoted.double.c constant.other.placeholder.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c constant.other.placeholder.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2487,7 +2509,7 @@ }, { "c": "+", - "t": "source.c meta.block.c string.quoted.double.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2498,7 +2520,7 @@ }, { "c": "%.2f", - "t": "source.c meta.block.c string.quoted.double.c constant.other.placeholder.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c constant.other.placeholder.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2509,7 +2531,7 @@ }, { "c": "i and ", - "t": "source.c meta.block.c string.quoted.double.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2520,7 +2542,7 @@ }, { "c": "%.2f", - "t": "source.c meta.block.c string.quoted.double.c constant.other.placeholder.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c constant.other.placeholder.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2531,7 +2553,7 @@ }, { "c": "-", - "t": "source.c meta.block.c string.quoted.double.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2542,7 +2564,7 @@ }, { "c": "%.2f", - "t": "source.c meta.block.c string.quoted.double.c constant.other.placeholder.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c constant.other.placeholder.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2553,7 +2575,7 @@ }, { "c": "i", - "t": "source.c meta.block.c string.quoted.double.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2564,7 +2586,7 @@ }, { "c": "\"", - "t": "source.c meta.block.c string.quoted.double.c punctuation.definition.string.end.c", + "t": "source.c meta.block.c meta.function-call.c string.quoted.double.c punctuation.definition.string.end.c", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -2575,7 +2597,7 @@ }, { "c": ",", - "t": "source.c meta.block.c punctuation.separator.delimiter.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.separator.delimiter.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2586,7 +2608,7 @@ }, { "c": " real", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2597,7 +2619,7 @@ }, { "c": ",", - "t": "source.c meta.block.c punctuation.separator.delimiter.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.separator.delimiter.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2608,7 +2630,7 @@ }, { "c": " imag", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2619,7 +2641,7 @@ }, { "c": ",", - "t": "source.c meta.block.c punctuation.separator.delimiter.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.separator.delimiter.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2630,7 +2652,7 @@ }, { "c": " real", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2641,7 +2663,7 @@ }, { "c": ",", - "t": "source.c meta.block.c punctuation.separator.delimiter.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.separator.delimiter.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2652,7 +2674,7 @@ }, { "c": " imag", - "t": "source.c meta.block.c", + "t": "source.c meta.block.c meta.function-call.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2663,7 +2685,7 @@ }, { "c": ")", - "t": "source.c meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.c meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2740,7 +2762,7 @@ }, { "c": "0", - "t": "source.c meta.block.c constant.numeric.c", + "t": "source.c meta.block.c constant.numeric.decimal.c", "r": { "dark_plus": "constant.numeric: #B5CEA8", "light_plus": "constant.numeric: #09885A", diff --git a/extensions/cpp/test/colorize-results/test_cc.json b/extensions/cpp/test/colorize-results/test_cc.json index f3f72320fb5..4567285df23 100644 --- a/extensions/cpp/test/colorize-results/test_cc.json +++ b/extensions/cpp/test/colorize-results/test_cc.json @@ -1,7 +1,7 @@ [ { "c": "#", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c punctuation.definition.directive.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp punctuation.definition.directive.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -12,7 +12,7 @@ }, { "c": "if", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -23,7 +23,7 @@ }, { "c": " ", - "t": "source.cpp meta.preprocessor.c", + "t": "source.cpp meta.preprocessor.cpp", "r": { "dark_plus": "meta.preprocessor: #569CD6", "light_plus": "meta.preprocessor: #0000FF", @@ -34,7 +34,7 @@ }, { "c": "B4G_DEBUG_CHECK", - "t": "source.cpp meta.preprocessor.c entity.name.function.preprocessor.c", + "t": "source.cpp meta.preprocessor.cpp entity.name.function.preprocessor.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -56,7 +56,7 @@ }, { "c": "fprintf", - "t": "source.cpp meta.function.c entity.name.function.c", + "t": "source.cpp entity.name.function.call.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -67,7 +67,7 @@ }, { "c": "(", - "t": "source.cpp meta.function.c punctuation.section.parameters.begin.bracket.round.c", + "t": "source.cpp punctuation.section.arguments.begin.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -78,7 +78,7 @@ }, { "c": "stderr", - "t": "source.cpp meta.function.c", + "t": "source.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -89,7 +89,7 @@ }, { "c": ",", - "t": "source.cpp meta.function.c punctuation.separator.delimiter.c", + "t": "source.cpp punctuation.separator.delimiter.comma.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -100,7 +100,7 @@ }, { "c": "\"", - "t": "source.cpp meta.function.c string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "t": "source.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -111,7 +111,7 @@ }, { "c": "num_candidate_ret=", - "t": "source.cpp meta.function.c string.quoted.double.cpp", + "t": "source.cpp string.quoted.double.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -122,7 +122,7 @@ }, { "c": "%d", - "t": "source.cpp meta.function.c string.quoted.double.cpp constant.other.placeholder.c", + "t": "source.cpp string.quoted.double.cpp constant.other.placeholder.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -133,7 +133,7 @@ }, { "c": ":", - "t": "source.cpp meta.function.c string.quoted.double.cpp", + "t": "source.cpp string.quoted.double.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -144,7 +144,7 @@ }, { "c": "\"", - "t": "source.cpp meta.function.c string.quoted.double.cpp punctuation.definition.string.end.cpp", + "t": "source.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -155,7 +155,7 @@ }, { "c": ",", - "t": "source.cpp meta.function.c punctuation.separator.delimiter.c", + "t": "source.cpp punctuation.separator.delimiter.comma.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -166,7 +166,7 @@ }, { "c": " num_candidate", - "t": "source.cpp meta.function.c", + "t": "source.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -177,7 +177,7 @@ }, { "c": ")", - "t": "source.cpp meta.function.c punctuation.section.parameters.end.bracket.round.c", + "t": "source.cpp punctuation.section.arguments.end.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -188,7 +188,7 @@ }, { "c": ";", - "t": "source.cpp punctuation.terminator.statement.c", + "t": "source.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -210,7 +210,7 @@ }, { "c": "for", - "t": "source.cpp keyword.control.c", + "t": "source.cpp keyword.control.for.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -221,7 +221,7 @@ }, { "c": "(", - "t": "source.cpp punctuation.section.parens.begin.bracket.round.c", + "t": "source.cpp meta.parens.cpp punctuation.section.parens.begin.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -232,7 +232,7 @@ }, { "c": "int", - "t": "source.cpp storage.type.c", + "t": "source.cpp meta.parens.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -243,7 +243,7 @@ }, { "c": " i", - "t": "source.cpp", + "t": "source.cpp meta.parens.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -254,7 +254,7 @@ }, { "c": "=", - "t": "source.cpp keyword.operator.assignment.c", + "t": "source.cpp meta.parens.cpp keyword.operator.assignment.cpp", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -265,7 +265,7 @@ }, { "c": "0", - "t": "source.cpp constant.numeric.c", + "t": "source.cpp meta.parens.cpp constant.numeric.decimal.cpp", "r": { "dark_plus": "constant.numeric: #B5CEA8", "light_plus": "constant.numeric: #09885A", @@ -276,7 +276,7 @@ }, { "c": ";", - "t": "source.cpp punctuation.terminator.statement.c", + "t": "source.cpp meta.parens.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -287,7 +287,7 @@ }, { "c": "i", - "t": "source.cpp", + "t": "source.cpp meta.parens.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -298,7 +298,7 @@ }, { "c": "<", - "t": "source.cpp keyword.operator.comparison.c", + "t": "source.cpp meta.parens.cpp keyword.operator.comparison.cpp", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -309,7 +309,7 @@ }, { "c": "num_candidate", - "t": "source.cpp", + "t": "source.cpp meta.parens.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -320,7 +320,7 @@ }, { "c": ";", - "t": "source.cpp punctuation.terminator.statement.c", + "t": "source.cpp meta.parens.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -331,7 +331,7 @@ }, { "c": "++", - "t": "source.cpp keyword.operator.increment.c", + "t": "source.cpp meta.parens.cpp keyword.operator.increment.cpp", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -342,7 +342,7 @@ }, { "c": "i", - "t": "source.cpp", + "t": "source.cpp meta.parens.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -353,7 +353,7 @@ }, { "c": ")", - "t": "source.cpp punctuation.section.parens.end.bracket.round.c", + "t": "source.cpp meta.parens.cpp punctuation.section.parens.end.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -375,7 +375,7 @@ }, { "c": "fprintf", - "t": "source.cpp meta.function.c entity.name.function.c", + "t": "source.cpp entity.name.function.call.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -386,7 +386,7 @@ }, { "c": "(", - "t": "source.cpp meta.function.c punctuation.section.parameters.begin.bracket.round.c", + "t": "source.cpp punctuation.section.arguments.begin.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -397,7 +397,7 @@ }, { "c": "stderr", - "t": "source.cpp meta.function.c", + "t": "source.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -408,7 +408,7 @@ }, { "c": ",", - "t": "source.cpp meta.function.c punctuation.separator.delimiter.c", + "t": "source.cpp punctuation.separator.delimiter.comma.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -419,7 +419,7 @@ }, { "c": "\"", - "t": "source.cpp meta.function.c string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "t": "source.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -430,7 +430,7 @@ }, { "c": "%d", - "t": "source.cpp meta.function.c string.quoted.double.cpp constant.other.placeholder.c", + "t": "source.cpp string.quoted.double.cpp constant.other.placeholder.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -441,7 +441,7 @@ }, { "c": ",", - "t": "source.cpp meta.function.c string.quoted.double.cpp", + "t": "source.cpp string.quoted.double.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -452,7 +452,7 @@ }, { "c": "\"", - "t": "source.cpp meta.function.c string.quoted.double.cpp punctuation.definition.string.end.cpp", + "t": "source.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -463,7 +463,7 @@ }, { "c": ",", - "t": "source.cpp meta.function.c punctuation.separator.delimiter.c", + "t": "source.cpp punctuation.separator.delimiter.comma.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -474,18 +474,18 @@ }, { "c": "user_candidate", - "t": "source.cpp meta.function.c", + "t": "source.cpp meta.bracket.square.access.cpp variable.other.object.cpp", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "variable: #9CDCFE" } }, { "c": "[", - "t": "source.cpp meta.function.c punctuation.definition.begin.bracket.square.c", + "t": "source.cpp meta.bracket.square.access.cpp punctuation.definition.begin.bracket.square.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -496,7 +496,7 @@ }, { "c": "i", - "t": "source.cpp meta.function.c", + "t": "source.cpp meta.bracket.square.access.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -507,7 +507,7 @@ }, { "c": "]", - "t": "source.cpp meta.function.c punctuation.definition.end.bracket.square.c", + "t": "source.cpp meta.bracket.square.access.cpp punctuation.definition.end.bracket.square.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -518,7 +518,7 @@ }, { "c": ")", - "t": "source.cpp meta.function.c punctuation.section.parameters.end.bracket.round.c", + "t": "source.cpp punctuation.section.arguments.end.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -529,7 +529,7 @@ }, { "c": ";", - "t": "source.cpp punctuation.terminator.statement.c", + "t": "source.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -551,7 +551,7 @@ }, { "c": "fprintf", - "t": "source.cpp meta.function.c entity.name.function.c", + "t": "source.cpp entity.name.function.call.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -562,7 +562,7 @@ }, { "c": "(", - "t": "source.cpp meta.function.c punctuation.section.parameters.begin.bracket.round.c", + "t": "source.cpp punctuation.section.arguments.begin.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -573,7 +573,7 @@ }, { "c": "stderr", - "t": "source.cpp meta.function.c", + "t": "source.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -584,7 +584,7 @@ }, { "c": ",", - "t": "source.cpp meta.function.c punctuation.separator.delimiter.c", + "t": "source.cpp punctuation.separator.delimiter.comma.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -595,7 +595,7 @@ }, { "c": "\"", - "t": "source.cpp meta.function.c string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "t": "source.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -606,7 +606,7 @@ }, { "c": ";", - "t": "source.cpp meta.function.c string.quoted.double.cpp", + "t": "source.cpp string.quoted.double.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -617,7 +617,7 @@ }, { "c": "\"", - "t": "source.cpp meta.function.c string.quoted.double.cpp punctuation.definition.string.end.cpp", + "t": "source.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -628,7 +628,7 @@ }, { "c": ")", - "t": "source.cpp meta.function.c punctuation.section.parameters.end.bracket.round.c", + "t": "source.cpp punctuation.section.arguments.end.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -639,7 +639,7 @@ }, { "c": ";", - "t": "source.cpp punctuation.terminator.statement.c", + "t": "source.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -650,7 +650,7 @@ }, { "c": "#", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c punctuation.definition.directive.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp punctuation.definition.directive.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -661,7 +661,7 @@ }, { "c": "endif", - "t": "source.cpp meta.preprocessor.c keyword.control.directive.conditional.c", + "t": "source.cpp meta.preprocessor.cpp keyword.control.directive.conditional.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -672,7 +672,7 @@ }, { "c": " ", - "t": "source.cpp", + "t": "source.cpp meta.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -683,7 +683,7 @@ }, { "c": "void", - "t": "source.cpp storage.type.c", + "t": "source.cpp meta.function.definition.cpp meta.qualified_type.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -694,7 +694,7 @@ }, { "c": " ", - "t": "source.cpp", + "t": "source.cpp meta.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -705,7 +705,7 @@ }, { "c": "main", - "t": "source.cpp meta.function.c entity.name.function.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp entity.name.function.definition.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -716,7 +716,7 @@ }, { "c": "(", - "t": "source.cpp meta.function.c punctuation.section.parameters.begin.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.begin.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -726,8 +726,19 @@ } }, { - "c": "O obj", - "t": "source.cpp meta.function.c", + "c": "O", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp entity.name.type.parameter.cpp", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -736,9 +747,20 @@ "hc_black": "default: #FFFFFF" } }, + { + "c": "obj", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp variable.parameter.cpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, { "c": ")", - "t": "source.cpp meta.function.c punctuation.section.parameters.end.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.end.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -749,7 +771,7 @@ }, { "c": " ", - "t": "source.cpp", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -760,7 +782,7 @@ }, { "c": "{", - "t": "source.cpp meta.block.c punctuation.section.block.begin.bracket.curly.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.block.begin.bracket.curly.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -771,7 +793,7 @@ }, { "c": " ", - "t": "source.cpp meta.block.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -782,7 +804,7 @@ }, { "c": "LOG_INFO", - "t": "source.cpp meta.block.c meta.function-call.c entity.name.function.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.function.call.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -793,7 +815,7 @@ }, { "c": "(", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.begin.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -804,7 +826,7 @@ }, { "c": "\"", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -815,7 +837,7 @@ }, { "c": "not hilighted as string", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -826,7 +848,7 @@ }, { "c": "\"", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp punctuation.definition.string.end.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -837,7 +859,7 @@ }, { "c": ")", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.end.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -848,7 +870,7 @@ }, { "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -859,7 +881,7 @@ }, { "c": " ", - "t": "source.cpp meta.block.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -870,7 +892,7 @@ }, { "c": "LOG_INFO", - "t": "source.cpp meta.block.c meta.function-call.c entity.name.function.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.function.call.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -881,7 +903,7 @@ }, { "c": "(", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.begin.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -892,7 +914,7 @@ }, { "c": "obj ", - "t": "source.cpp meta.block.c meta.function-call.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -903,7 +925,7 @@ }, { "c": "<<", - "t": "source.cpp meta.block.c meta.function-call.c keyword.operator.bitwise.shift.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.bitwise.shift.cpp", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -914,7 +936,7 @@ }, { "c": " ", - "t": "source.cpp meta.block.c meta.function-call.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -925,7 +947,7 @@ }, { "c": "\"", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -936,7 +958,7 @@ }, { "c": ", even worse; ", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -947,7 +969,7 @@ }, { "c": "\"", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp punctuation.definition.string.end.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -958,7 +980,7 @@ }, { "c": " ", - "t": "source.cpp meta.block.c meta.function-call.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -969,7 +991,7 @@ }, { "c": "<<", - "t": "source.cpp meta.block.c meta.function-call.c keyword.operator.bitwise.shift.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.bitwise.shift.cpp", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -979,8 +1001,8 @@ } }, { - "c": " obj", - "t": "source.cpp meta.block.c meta.function-call.c", + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -989,9 +1011,20 @@ "hc_black": "default: #FFFFFF" } }, + { + "c": "obj", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp variable.other.object.access.cpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, { "c": ".", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.separator.dot-access.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.separator.dot-access.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1002,7 +1035,7 @@ }, { "c": "x", - "t": "source.cpp meta.block.c meta.function-call.c variable.other.member.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp variable.other.property.cpp", "r": { "dark_plus": "variable: #9CDCFE", "light_plus": "variable: #001080", @@ -1013,7 +1046,7 @@ }, { "c": " ", - "t": "source.cpp meta.block.c meta.function-call.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1024,7 +1057,7 @@ }, { "c": "<<", - "t": "source.cpp meta.block.c meta.function-call.c keyword.operator.bitwise.shift.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.bitwise.shift.cpp", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1035,7 +1068,7 @@ }, { "c": " ", - "t": "source.cpp meta.block.c meta.function-call.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1046,7 +1079,7 @@ }, { "c": "\"", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1057,7 +1090,7 @@ }, { "c": " check this out.", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1068,7 +1101,7 @@ }, { "c": "\"", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp punctuation.definition.string.end.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1079,7 +1112,7 @@ }, { "c": ")", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.end.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1090,7 +1123,7 @@ }, { "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1101,18 +1134,18 @@ }, { "c": " ", - "t": "source.cpp meta.block.c punctuation.whitespace.comment.leading.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" } }, { "c": "//", - "t": "source.cpp meta.block.c comment.line.double-slash.cpp punctuation.definition.comment.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp punctuation.definition.comment.cpp", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -1123,7 +1156,7 @@ }, { "c": " everything from this point on is interpeted as a string literal...", - "t": "source.cpp meta.block.c comment.line.double-slash.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -1134,7 +1167,7 @@ }, { "c": " O x", - "t": "source.cpp meta.block.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1145,7 +1178,7 @@ }, { "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1155,8 +1188,8 @@ } }, { - "c": " std", - "t": "source.cpp meta.block.c", + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1165,9 +1198,20 @@ "hc_black": "default: #FFFFFF" } }, + { + "c": "std", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.scope-resolution.cpp", + "r": { + "dark_plus": "entity.name.scope-resolution: #4EC9B0", + "light_plus": "entity.name.scope-resolution: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.scope-resolution: #4EC9B0" + } + }, { "c": "::", - "t": "source.cpp meta.block.c punctuation.separator.namespace.access.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1178,7 +1222,7 @@ }, { "c": "unique_ptr", - "t": "source.cpp meta.block.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1189,7 +1233,7 @@ }, { "c": "<", - "t": "source.cpp meta.block.c keyword.operator.comparison.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.comparison.cpp", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1200,7 +1244,7 @@ }, { "c": "O", - "t": "source.cpp meta.block.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1211,7 +1255,7 @@ }, { "c": ">", - "t": "source.cpp meta.block.c keyword.operator.comparison.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.comparison.cpp", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1222,7 +1266,7 @@ }, { "c": " ", - "t": "source.cpp meta.block.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1233,7 +1277,7 @@ }, { "c": "o", - "t": "source.cpp meta.block.c meta.function-call.c entity.name.function.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.function.call.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -1244,7 +1288,7 @@ }, { "c": "(", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.begin.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1255,18 +1299,18 @@ }, { "c": "new", - "t": "source.cpp meta.block.c meta.function-call.c keyword.control.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.wordlike.cpp keyword.operator.new.cpp", "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" + "dark_plus": "source.cpp keyword.operator.new: #C586C0", + "light_plus": "source.cpp keyword.operator.new: #AF00DB", + "dark_vs": "keyword.operator.new: #569CD6", + "light_vs": "keyword.operator.new: #0000FF", + "hc_black": "source.cpp keyword.operator.new: #C586C0" } }, { "c": " O", - "t": "source.cpp meta.block.c meta.function-call.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1277,7 +1321,7 @@ }, { "c": ")", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.end.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1288,7 +1332,7 @@ }, { "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1299,18 +1343,18 @@ }, { "c": " ", - "t": "source.cpp meta.block.c punctuation.whitespace.comment.leading.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" } }, { "c": "//", - "t": "source.cpp meta.block.c comment.line.double-slash.cpp punctuation.definition.comment.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp punctuation.definition.comment.cpp", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -1321,7 +1365,7 @@ }, { "c": " sadness.", - "t": "source.cpp meta.block.c comment.line.double-slash.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -1332,7 +1376,7 @@ }, { "c": " ", - "t": "source.cpp meta.block.c punctuation.whitespace.support.function.leading.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1343,18 +1387,18 @@ }, { "c": "sprintf", - "t": "source.cpp meta.block.c support.function.C99.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.function.call.cpp", "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" + "hc_black": "entity.name.function: #DCDCAA" } }, { "c": "(", - "t": "source.cpp meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.begin.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1365,7 +1409,7 @@ }, { "c": "options", - "t": "source.cpp meta.block.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1376,7 +1420,7 @@ }, { "c": ",", - "t": "source.cpp meta.block.c punctuation.separator.delimiter.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.separator.delimiter.comma.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1387,7 +1431,7 @@ }, { "c": " ", - "t": "source.cpp meta.block.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1398,7 +1442,7 @@ }, { "c": "\"", - "t": "source.cpp meta.block.c string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1409,7 +1453,7 @@ }, { "c": "STYLE=Keramik;TITLE=", - "t": "source.cpp meta.block.c string.quoted.double.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1420,7 +1464,7 @@ }, { "c": "%s", - "t": "source.cpp meta.block.c string.quoted.double.cpp constant.other.placeholder.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp constant.other.placeholder.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1431,7 +1475,7 @@ }, { "c": ";THEME=", - "t": "source.cpp meta.block.c string.quoted.double.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1442,7 +1486,7 @@ }, { "c": "%s", - "t": "source.cpp meta.block.c string.quoted.double.cpp constant.other.placeholder.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp constant.other.placeholder.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1453,7 +1497,7 @@ }, { "c": "\"", - "t": "source.cpp meta.block.c string.quoted.double.cpp punctuation.definition.string.end.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1464,7 +1508,7 @@ }, { "c": ",", - "t": "source.cpp meta.block.c punctuation.separator.delimiter.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.separator.delimiter.comma.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1474,19 +1518,8 @@ } }, { - "c": " ", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "...", - "t": "source.cpp meta.block.c punctuation.separator.dot-access.c", + "c": " ...", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1497,7 +1530,7 @@ }, { "c": ")", - "t": "source.cpp meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.end.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1508,7 +1541,7 @@ }, { "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1519,7 +1552,7 @@ }, { "c": "}", - "t": "source.cpp meta.block.c punctuation.section.block.end.bracket.curly.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.block.end.bracket.curly.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1530,7 +1563,7 @@ }, { "c": "int", - "t": "source.cpp storage.type.c", + "t": "source.cpp meta.function.definition.cpp meta.qualified_type.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -1541,7 +1574,7 @@ }, { "c": " ", - "t": "source.cpp", + "t": "source.cpp meta.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1552,7 +1585,7 @@ }, { "c": "main2", - "t": "source.cpp meta.function.c entity.name.function.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp entity.name.function.definition.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -1563,7 +1596,7 @@ }, { "c": "(", - "t": "source.cpp meta.function.c punctuation.section.parameters.begin.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.begin.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1574,7 +1607,7 @@ }, { "c": ")", - "t": "source.cpp meta.function.c punctuation.section.parameters.end.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.end.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1585,7 +1618,7 @@ }, { "c": " ", - "t": "source.cpp", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1596,7 +1629,7 @@ }, { "c": "{", - "t": "source.cpp meta.block.c punctuation.section.block.begin.bracket.curly.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.block.begin.bracket.curly.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1607,7 +1640,7 @@ }, { "c": " ", - "t": "source.cpp meta.block.c punctuation.whitespace.support.function.leading.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1618,260 +1651,7 @@ }, { "c": "printf", - "t": "source.cpp meta.block.c support.function.C99.c", - "r": { - "dark_plus": "support.function: #DCDCAA", - "light_plus": "support.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "support.function: #DCDCAA" - } - }, - { - "c": "(", - "t": "source.cpp meta.block.c punctuation.section.parens.begin.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\"", - "t": "source.cpp meta.block.c string.quoted.double.cpp punctuation.definition.string.begin.cpp", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": ";", - "t": "source.cpp meta.block.c string.quoted.double.cpp", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "\"", - "t": "source.cpp meta.block.c string.quoted.double.cpp punctuation.definition.string.end.cpp", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": ")", - "t": "source.cpp meta.block.c punctuation.section.parens.end.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.cpp meta.block.c punctuation.whitespace.comment.leading.cpp", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "//", - "t": "source.cpp meta.block.c comment.line.double-slash.cpp punctuation.definition.comment.cpp", - "r": { - "dark_plus": "comment: #6A9955", - "light_plus": "comment: #008000", - "dark_vs": "comment: #6A9955", - "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" - } - }, - { - "c": " the rest of", - "t": "source.cpp meta.block.c comment.line.double-slash.cpp", - "r": { - "dark_plus": "comment: #6A9955", - "light_plus": "comment: #008000", - "dark_vs": "comment: #6A9955", - "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" - } - }, - { - "c": " ", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "asm", - "t": "source.cpp meta.block.c meta.function-call.c storage.type.c", - "r": { - "dark_plus": "storage.type: #569CD6", - "light_plus": "storage.type: #0000FF", - "dark_vs": "storage.type: #569CD6", - "light_vs": "storage.type: #0000FF", - "hc_black": "storage.type: #569CD6" - } - }, - { - "c": "(", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.parens.begin.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\"", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp punctuation.definition.string.begin.cpp", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "movw $0x38, ", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "%a", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp constant.other.placeholder.c", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "x; ltr ", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "%a", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp constant.other.placeholder.c", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "x", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "\"", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp punctuation.definition.string.end.cpp", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": ")", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.parens.end.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "fn", - "t": "source.cpp meta.block.c meta.function-call.c entity.name.function.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.function.call.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -1882,7 +1662,7 @@ }, { "c": "(", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.begin.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1893,7 +1673,7 @@ }, { "c": "\"", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1903,8 +1683,8 @@ } }, { - "c": "{};", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp", + "c": ";", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1915,7 +1695,7 @@ }, { "c": "\"", - "t": "source.cpp meta.block.c meta.function-call.c string.quoted.double.cpp punctuation.definition.string.end.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1926,7 +1706,7 @@ }, { "c": ")", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.end.bracket.round.function.call.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1937,7 +1717,7 @@ }, { "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1948,18 +1728,18 @@ }, { "c": " ", - "t": "source.cpp meta.block.c punctuation.whitespace.comment.leading.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" } }, { "c": "//", - "t": "source.cpp meta.block.c comment.line.double-slash.cpp punctuation.definition.comment.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp punctuation.definition.comment.cpp", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -1970,7 +1750,216 @@ }, { "c": " the rest of", - "t": "source.cpp meta.block.c comment.line.double-slash.cpp", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "asm", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp storage.type.asm.cpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "(", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp punctuation.section.parens.begin.bracket.round.assembly.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\"", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp string.quoted.double.cpp punctuation.definition.string.begin.assembly.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "movw $0x38, %ax; ltr %ax", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp string.quoted.double.cpp meta.embedded.assembly.cpp", + "r": { + "dark_plus": "meta.embedded: #D4D4D4", + "light_plus": "meta.embedded: #000000", + "dark_vs": "meta.embedded: #D4D4D4", + "light_vs": "meta.embedded: #000000", + "hc_black": "meta.embedded: #FFFFFF" + } + }, + { + "c": "\"", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp string.quoted.double.cpp punctuation.definition.string.end.assembly.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": ")", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp punctuation.section.parens.end.bracket.round.assembly.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "fn", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.function.call.cpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": "(", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.begin.bracket.round.function.call.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\"", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "{};", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "\"", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": ")", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.end.bracket.round.function.call.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "//", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp punctuation.definition.comment.cpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " the rest of", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -1981,7 +1970,7 @@ }, { "c": "}", - "t": "source.cpp meta.block.c punctuation.section.block.end.bracket.curly.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.block.end.bracket.curly.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", diff --git a/extensions/cpp/test/colorize-results/test_cpp.json b/extensions/cpp/test/colorize-results/test_cpp.json index b3c9a841cc4..025f668b4c9 100644 --- a/extensions/cpp/test/colorize-results/test_cpp.json +++ b/extensions/cpp/test/colorize-results/test_cpp.json @@ -23,7 +23,7 @@ }, { "c": "#", - "t": "source.cpp meta.preprocessor.include.c keyword.control.directive.include.c punctuation.definition.directive.c", + "t": "source.cpp meta.preprocessor.include.cpp keyword.control.directive.include.cpp punctuation.definition.directive.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -34,7 +34,7 @@ }, { "c": "include", - "t": "source.cpp meta.preprocessor.include.c keyword.control.directive.include.c", + "t": "source.cpp meta.preprocessor.include.cpp keyword.control.directive.include.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -45,7 +45,7 @@ }, { "c": " ", - "t": "source.cpp meta.preprocessor.include.c", + "t": "source.cpp meta.preprocessor.include.cpp", "r": { "dark_plus": "meta.preprocessor: #569CD6", "light_plus": "meta.preprocessor: #0000FF", @@ -56,7 +56,7 @@ }, { "c": "<", - "t": "source.cpp meta.preprocessor.include.c string.quoted.other.lt-gt.include.c punctuation.definition.string.begin.c", + "t": "source.cpp meta.preprocessor.include.cpp string.quoted.other.lt-gt.include.cpp punctuation.definition.string.begin.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -67,7 +67,7 @@ }, { "c": "iostream", - "t": "source.cpp meta.preprocessor.include.c string.quoted.other.lt-gt.include.c", + "t": "source.cpp meta.preprocessor.include.cpp string.quoted.other.lt-gt.include.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -78,7 +78,7 @@ }, { "c": ">", - "t": "source.cpp meta.preprocessor.include.c string.quoted.other.lt-gt.include.c punctuation.definition.string.end.c", + "t": "source.cpp meta.preprocessor.include.cpp string.quoted.other.lt-gt.include.cpp punctuation.definition.string.end.cpp", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -89,18 +89,18 @@ }, { "c": "using", - "t": "source.cpp meta.using-namespace-declaration.cpp keyword.control.cpp", + "t": "source.cpp meta.using-namespace.cpp keyword.other.using.directive.cpp", "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" + "dark_plus": "keyword.other.using: #C586C0", + "light_plus": "keyword.other.using: #AF00DB", + "dark_vs": "keyword: #569CD6", + "light_vs": "keyword: #0000FF", + "hc_black": "keyword.other.using: #C586C0" } }, { "c": " ", - "t": "source.cpp meta.using-namespace-declaration.cpp", + "t": "source.cpp meta.using-namespace.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -111,7 +111,7 @@ }, { "c": "namespace", - "t": "source.cpp meta.using-namespace-declaration.cpp storage.type.cpp", + "t": "source.cpp meta.using-namespace.cpp keyword.other.namespace.directive.cpp storage.type.namespace.directive.cpp", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -122,7 +122,7 @@ }, { "c": " ", - "t": "source.cpp meta.using-namespace-declaration.cpp", + "t": "source.cpp meta.using-namespace.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -133,18 +133,18 @@ }, { "c": "std", - "t": "source.cpp meta.using-namespace-declaration.cpp entity.name.type.cpp", + "t": "source.cpp meta.using-namespace.cpp entity.name.namespace.cpp", "r": { - "dark_plus": "entity.name.type: #4EC9B0", - "light_plus": "entity.name.type: #267F99", + "dark_plus": "entity.name.namespace: #4EC9B0", + "light_plus": "entity.name.namespace: #267F99", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "entity.name.type: #4EC9B0" + "hc_black": "entity.name.namespace: #4EC9B0" } }, { "c": ";", - "t": "source.cpp meta.using-namespace-declaration.cpp", + "t": "source.cpp meta.using-namespace.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -154,8 +154,63 @@ } }, { - "c": "class", - "t": "source.cpp meta.class-struct-block.cpp storage.type.cpp", + "c": "#", + "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp punctuation.definition.directive.cpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": "define", + "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": " ", + "t": "source.cpp meta.preprocessor.macro.cpp", + "r": { + "dark_plus": "meta.preprocessor: #569CD6", + "light_plus": "meta.preprocessor: #0000FF", + "dark_vs": "meta.preprocessor: #569CD6", + "light_vs": "meta.preprocessor: #0000FF", + "hc_black": "meta.preprocessor: #569CD6" + } + }, + { + "c": "EXTERN_C", + "t": "source.cpp meta.preprocessor.macro.cpp entity.name.function.preprocessor.cpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "meta.preprocessor: #569CD6", + "light_vs": "meta.preprocessor: #0000FF", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": " ", + "t": "source.cpp meta.preprocessor.macro.cpp meta.block.extern.cpp", + "r": { + "dark_plus": "meta.preprocessor: #569CD6", + "light_plus": "meta.preprocessor: #0000FF", + "dark_vs": "meta.preprocessor: #569CD6", + "light_vs": "meta.preprocessor: #0000FF", + "hc_black": "meta.preprocessor: #569CD6" + } + }, + { + "c": "extern", + "t": "source.cpp meta.preprocessor.macro.cpp meta.block.extern.cpp meta.head.extern.cpp storage.type.extern.cpp", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -166,7 +221,62 @@ }, { "c": " ", - "t": "source.cpp meta.class-struct-block.cpp", + "t": "source.cpp meta.preprocessor.macro.cpp meta.block.extern.cpp meta.head.extern.cpp", + "r": { + "dark_plus": "meta.preprocessor: #569CD6", + "light_plus": "meta.preprocessor: #0000FF", + "dark_vs": "meta.preprocessor: #569CD6", + "light_vs": "meta.preprocessor: #0000FF", + "hc_black": "meta.preprocessor: #569CD6" + } + }, + { + "c": "\"", + "t": "source.cpp meta.preprocessor.macro.cpp meta.block.extern.cpp meta.head.extern.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "C", + "t": "source.cpp meta.preprocessor.macro.cpp meta.block.extern.cpp meta.head.extern.cpp string.quoted.double.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "\"", + "t": "source.cpp meta.preprocessor.macro.cpp meta.block.extern.cpp meta.head.extern.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "class", + "t": "source.cpp meta.block.class.cpp meta.head.class.cpp storage.type.class.cpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ", + "t": "source.cpp meta.block.class.cpp meta.head.class.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -177,7 +287,7 @@ }, { "c": "Rectangle", - "t": "source.cpp meta.class-struct-block.cpp entity.name.type.cpp", + "t": "source.cpp meta.block.class.cpp meta.head.class.cpp entity.name.type.class.cpp", "r": { "dark_plus": "entity.name.type: #4EC9B0", "light_plus": "entity.name.type: #267F99", @@ -188,7 +298,7 @@ }, { "c": " ", - "t": "source.cpp meta.class-struct-block.cpp", + "t": "source.cpp meta.block.class.cpp meta.head.class.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -199,7 +309,7 @@ }, { "c": "{", - "t": "source.cpp meta.class-struct-block.cpp punctuation.section.block.begin.bracket.curly.cpp", + "t": "source.cpp meta.block.class.cpp meta.head.class.cpp punctuation.section.block.begin.bracket.curly.class.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -210,7 +320,7 @@ }, { "c": " ", - "t": "source.cpp meta.class-struct-block.cpp", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -221,7 +331,7 @@ }, { "c": "int", - "t": "source.cpp meta.class-struct-block.cpp storage.type.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -232,7 +342,7 @@ }, { "c": " width", - "t": "source.cpp meta.class-struct-block.cpp", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -243,7 +353,7 @@ }, { "c": ",", - "t": "source.cpp meta.class-struct-block.cpp punctuation.separator.delimiter.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp punctuation.separator.delimiter.comma.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -254,7 +364,7 @@ }, { "c": " height", - "t": "source.cpp meta.class-struct-block.cpp", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -265,7 +375,7 @@ }, { "c": ";", - "t": "source.cpp meta.class-struct-block.cpp punctuation.terminator.statement.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -276,7 +386,7 @@ }, { "c": " ", - "t": "source.cpp meta.class-struct-block.cpp", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -286,19 +396,30 @@ } }, { - "c": "public:", - "t": "source.cpp meta.class-struct-block.cpp storage.modifier.cpp", + "c": "public", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp storage.type.modifier.access.control.public.cpp", "r": { - "dark_plus": "storage.modifier: #569CD6", - "light_plus": "storage.modifier: #0000FF", - "dark_vs": "storage.modifier: #569CD6", - "light_vs": "storage.modifier: #0000FF", - "hc_black": "storage.modifier: #569CD6" + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": ":", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp storage.type.modifier.access.control.public.cpp punctuation.separator.colon.access.control.cpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" } }, { "c": " ", - "t": "source.cpp meta.class-struct-block.cpp", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -309,7 +430,7 @@ }, { "c": "void", - "t": "source.cpp meta.class-struct-block.cpp storage.type.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.qualified_type.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -320,7 +441,7 @@ }, { "c": " ", - "t": "source.cpp meta.class-struct-block.cpp", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -331,7 +452,7 @@ }, { "c": "set_values", - "t": "source.cpp meta.class-struct-block.cpp meta.function.c entity.name.function.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.head.function.definition.cpp entity.name.function.definition.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -342,7 +463,7 @@ }, { "c": " ", - "t": "source.cpp meta.class-struct-block.cpp meta.function.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -353,7 +474,7 @@ }, { "c": "(", - "t": "source.cpp meta.class-struct-block.cpp meta.function.c punctuation.section.parameters.begin.bracket.round.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.begin.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -364,7 +485,7 @@ }, { "c": "int", - "t": "source.cpp meta.class-struct-block.cpp meta.function.c storage.type.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -375,7 +496,7 @@ }, { "c": ",", - "t": "source.cpp meta.class-struct-block.cpp meta.function.c punctuation.separator.delimiter.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp punctuation.separator.delimiter.comma.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -386,7 +507,7 @@ }, { "c": "int", - "t": "source.cpp meta.class-struct-block.cpp meta.function.c storage.type.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -397,7 +518,7 @@ }, { "c": ")", - "t": "source.cpp meta.class-struct-block.cpp meta.function.c punctuation.section.parameters.end.bracket.round.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.end.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -408,7 +529,7 @@ }, { "c": ";", - "t": "source.cpp meta.class-struct-block.cpp punctuation.terminator.statement.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -419,7 +540,7 @@ }, { "c": " ", - "t": "source.cpp meta.class-struct-block.cpp", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -430,7 +551,7 @@ }, { "c": "int", - "t": "source.cpp meta.class-struct-block.cpp storage.type.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.qualified_type.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -441,7 +562,7 @@ }, { "c": " ", - "t": "source.cpp meta.class-struct-block.cpp", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -452,7 +573,7 @@ }, { "c": "area", - "t": "source.cpp meta.class-struct-block.cpp meta.function.c entity.name.function.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.head.function.definition.cpp entity.name.function.definition.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -463,7 +584,7 @@ }, { "c": "(", - "t": "source.cpp meta.class-struct-block.cpp meta.function.c punctuation.section.parameters.begin.bracket.round.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.begin.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -474,7 +595,7 @@ }, { "c": ")", - "t": "source.cpp meta.class-struct-block.cpp meta.function.c punctuation.section.parameters.end.bracket.round.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.end.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -485,7 +606,7 @@ }, { "c": " ", - "t": "source.cpp meta.class-struct-block.cpp", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.head.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -496,7 +617,7 @@ }, { "c": "{", - "t": "source.cpp meta.class-struct-block.cpp meta.block.c punctuation.section.block.begin.bracket.curly.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.block.begin.bracket.curly.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -507,7 +628,7 @@ }, { "c": "return", - "t": "source.cpp meta.class-struct-block.cpp meta.block.c keyword.control.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.control.return.cpp", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -518,7 +639,7 @@ }, { "c": " width", - "t": "source.cpp meta.class-struct-block.cpp meta.block.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -529,7 +650,7 @@ }, { "c": "*", - "t": "source.cpp meta.class-struct-block.cpp meta.block.c keyword.operator.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.cpp", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -540,7 +661,7 @@ }, { "c": "height", - "t": "source.cpp meta.class-struct-block.cpp meta.block.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -551,7 +672,7 @@ }, { "c": ";", - "t": "source.cpp meta.class-struct-block.cpp meta.block.c punctuation.terminator.statement.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -562,7 +683,7 @@ }, { "c": "}", - "t": "source.cpp meta.class-struct-block.cpp meta.block.c punctuation.section.block.end.bracket.curly.c", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.block.end.bracket.curly.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -573,7 +694,7 @@ }, { "c": "}", - "t": "source.cpp meta.class-struct-block.cpp punctuation.section.block.end.bracket.curly.cpp", + "t": "source.cpp meta.block.class.cpp meta.body.class.cpp punctuation.section.block.end.bracket.curly.class.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -584,7 +705,7 @@ }, { "c": ";", - "t": "source.cpp punctuation.terminator.statement.c", + "t": "source.cpp meta.block.class.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -595,7 +716,7 @@ }, { "c": "void", - "t": "source.cpp storage.type.c", + "t": "source.cpp meta.function.definition.cpp meta.qualified_type.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -606,7 +727,7 @@ }, { "c": " ", - "t": "source.cpp", + "t": "source.cpp meta.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -616,360 +737,19 @@ } }, { - "c": "Rectangle::set_values", - "t": "source.cpp meta.function.c entity.name.function.c", + "c": "Rectangle", + "t": "source.cpp meta.function.definition.cpp entity.name.scope-resolution.function.definition.cpp", "r": { - "dark_plus": "entity.name.function: #DCDCAA", - "light_plus": "entity.name.function: #795E26", + "dark_plus": "entity.name.scope-resolution: #4EC9B0", + "light_plus": "entity.name.scope-resolution: #267F99", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "entity.name.function: #DCDCAA" + "hc_black": "entity.name.scope-resolution: #4EC9B0" } }, { - "c": " ", - "t": "source.cpp meta.function.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "(", - "t": "source.cpp meta.function.c punctuation.section.parameters.begin.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "int", - "t": "source.cpp meta.function.c storage.type.c", - "r": { - "dark_plus": "storage.type: #569CD6", - "light_plus": "storage.type: #0000FF", - "dark_vs": "storage.type: #569CD6", - "light_vs": "storage.type: #0000FF", - "hc_black": "storage.type: #569CD6" - } - }, - { - "c": " x", - "t": "source.cpp meta.function.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ",", - "t": "source.cpp meta.function.c punctuation.separator.delimiter.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.cpp meta.function.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "int", - "t": "source.cpp meta.function.c storage.type.c", - "r": { - "dark_plus": "storage.type: #569CD6", - "light_plus": "storage.type: #0000FF", - "dark_vs": "storage.type: #569CD6", - "light_vs": "storage.type: #0000FF", - "hc_black": "storage.type: #569CD6" - } - }, - { - "c": " y", - "t": "source.cpp meta.function.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ")", - "t": "source.cpp meta.function.c punctuation.section.parameters.end.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.cpp", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "{", - "t": "source.cpp meta.block.c punctuation.section.block.begin.bracket.curly.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " width ", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "=", - "t": "source.cpp meta.block.c keyword.operator.assignment.c", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " x", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " height ", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "=", - "t": "source.cpp meta.block.c keyword.operator.assignment.c", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " y", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "}", - "t": "source.cpp meta.block.c punctuation.section.block.end.bracket.curly.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "int", - "t": "source.cpp storage.type.c", - "r": { - "dark_plus": "storage.type: #569CD6", - "light_plus": "storage.type: #0000FF", - "dark_vs": "storage.type: #569CD6", - "light_vs": "storage.type: #0000FF", - "hc_black": "storage.type: #569CD6" - } - }, - { - "c": " ", - "t": "source.cpp", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "main", - "t": "source.cpp meta.function.c entity.name.function.c", - "r": { - "dark_plus": "entity.name.function: #DCDCAA", - "light_plus": "entity.name.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "entity.name.function: #DCDCAA" - } - }, - { - "c": " ", - "t": "source.cpp meta.function.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "(", - "t": "source.cpp meta.function.c punctuation.section.parameters.begin.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ")", - "t": "source.cpp meta.function.c punctuation.section.parameters.end.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.cpp", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "{", - "t": "source.cpp meta.block.c punctuation.section.block.begin.bracket.curly.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " Rectangle rect", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " rect", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ".", - "t": "source.cpp meta.block.c punctuation.separator.dot-access.c", + "c": "::", + "t": "source.cpp meta.function.definition.cpp punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -980,7 +760,7 @@ }, { "c": "set_values", - "t": "source.cpp meta.block.c meta.function-call.c entity.name.function.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp entity.name.function.definition.cpp", "r": { "dark_plus": "entity.name.function: #DCDCAA", "light_plus": "entity.name.function: #795E26", @@ -991,7 +771,7 @@ }, { "c": " ", - "t": "source.cpp meta.block.c meta.function-call.c", + "t": "source.cpp meta.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1002,7 +782,7 @@ }, { "c": "(", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.begin.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1012,19 +792,41 @@ } }, { - "c": "3", - "t": "source.cpp meta.block.c meta.function-call.c constant.numeric.c", + "c": "int", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", "r": { - "dark_plus": "constant.numeric: #B5CEA8", - "light_plus": "constant.numeric: #09885A", - "dark_vs": "constant.numeric: #B5CEA8", - "light_vs": "constant.numeric: #09885A", - "hc_black": "constant.numeric: #B5CEA8" + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "x", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp variable.parameter.cpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" } }, { "c": ",", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.separator.delimiter.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp punctuation.separator.delimiter.comma.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1034,19 +836,52 @@ } }, { - "c": "4", - "t": "source.cpp meta.block.c meta.function-call.c constant.numeric.c", + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp", "r": { - "dark_plus": "constant.numeric: #B5CEA8", - "light_plus": "constant.numeric: #09885A", - "dark_vs": "constant.numeric: #B5CEA8", - "light_vs": "constant.numeric: #09885A", - "hc_black": "constant.numeric: #B5CEA8" + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "int", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "y", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp meta.function.definition.parameters.cpp meta.parameter.cpp variable.parameter.cpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" } }, { "c": ")", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.end.bracket.round.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1056,8 +891,8 @@ } }, { - "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1067,8 +902,8 @@ } }, { - "c": " cout ", - "t": "source.cpp meta.block.c", + "c": "{", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.block.begin.bracket.curly.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1078,8 +913,19 @@ } }, { - "c": "<<", - "t": "source.cpp meta.block.c keyword.operator.bitwise.shift.c", + "c": " width ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.assignment.cpp", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1089,8 +935,8 @@ } }, { - "c": " ", - "t": "source.cpp meta.block.c", + "c": " x", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1100,41 +946,8 @@ } }, { - "c": "\"", - "t": "source.cpp meta.block.c string.quoted.double.cpp punctuation.definition.string.begin.cpp", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "area: ", - "t": "source.cpp meta.block.c string.quoted.double.cpp", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": "\"", - "t": "source.cpp meta.block.c string.quoted.double.cpp punctuation.definition.string.end.cpp", - "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" - } - }, - { - "c": " ", - "t": "source.cpp meta.block.c", + "c": ";", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1144,8 +957,19 @@ } }, { - "c": "<<", - "t": "source.cpp meta.block.c keyword.operator.bitwise.shift.c", + "c": " height ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.assignment.cpp", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -1155,52 +979,8 @@ } }, { - "c": " rect", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ".", - "t": "source.cpp meta.block.c punctuation.separator.dot-access.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "area", - "t": "source.cpp meta.block.c meta.function-call.c entity.name.function.c", - "r": { - "dark_plus": "entity.name.function: #DCDCAA", - "light_plus": "entity.name.function: #795E26", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "entity.name.function: #DCDCAA" - } - }, - { - "c": "(", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.begin.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ")", - "t": "source.cpp meta.block.c meta.function-call.c punctuation.section.arguments.end.bracket.round.c", + "c": " y", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1211,62 +991,7 @@ }, { "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "return", - "t": "source.cpp meta.block.c keyword.control.c", - "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" - } - }, - { - "c": " ", - "t": "source.cpp meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "0", - "t": "source.cpp meta.block.c constant.numeric.c", - "r": { - "dark_plus": "constant.numeric: #B5CEA8", - "light_plus": "constant.numeric: #09885A", - "dark_vs": "constant.numeric: #B5CEA8", - "light_vs": "constant.numeric: #09885A", - "hc_black": "constant.numeric: #B5CEA8" - } - }, - { - "c": ";", - "t": "source.cpp meta.block.c punctuation.terminator.statement.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1277,7 +1002,865 @@ }, { "c": "}", - "t": "source.cpp meta.block.c punctuation.section.block.end.bracket.curly.c", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.block.end.bracket.curly.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "int", + "t": "source.cpp meta.function.definition.cpp meta.qualified_type.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "main", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp entity.name.function.definition.cpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "(", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.begin.bracket.round.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ")", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.parameters.end.bracket.round.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "{", + "t": "source.cpp meta.function.definition.cpp meta.head.function.definition.cpp punctuation.section.block.begin.bracket.curly.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " Rectangle rect", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "rect", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp variable.other.object.access.cpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.separator.dot-access.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "set_values", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.function.member.cpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "(", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.begin.bracket.round.function.member.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "3", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.numeric.decimal.cpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ",", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.separator.delimiter.comma.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "4", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.numeric.decimal.cpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ")", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.end.bracket.round.function.member.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " cout ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "<<", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.bitwise.shift.cpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\"", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "area: ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "\"", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "<<", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.bitwise.shift.cpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "rect", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp variable.other.object.access.cpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.separator.dot-access.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "area", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.function.member.cpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": "(", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.begin.bracket.round.function.member.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ")", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.end.bracket.round.function.member.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "Task", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.scope-resolution.cpp", + "r": { + "dark_plus": "entity.name.scope-resolution: #4EC9B0", + "light_plus": "entity.name.scope-resolution: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.scope-resolution: #4EC9B0" + } + }, + { + "c": "<", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.template.call.cpp meta.template.call.cpp punctuation.section.angle-brackets.begin.template.call.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "ANY_OUTPUT_TYPE", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.template.call.cpp meta.template.call.cpp meta.qualified_type.cpp entity.name.type.cpp", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": ",", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.template.call.cpp meta.template.call.cpp punctuation.separator.delimiter.comma.template.argument.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.template.call.cpp meta.template.call.cpp meta.qualified_type.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "ANY_INPUT_TYPE", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.template.call.cpp meta.template.call.cpp meta.qualified_type.cpp entity.name.type.cpp", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": ">", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.template.call.cpp meta.template.call.cpp punctuation.section.angle-brackets.end.template.call.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "::", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "links_to", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "int", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " t ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.assignment.cpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "2", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.numeric.decimal.cpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ";", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "if", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.control.if.cpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "(", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.parens.cpp punctuation.section.parens.begin.bracket.round.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "t ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.parens.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ">", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.parens.cpp keyword.operator.comparison.cpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.parens.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "0", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.parens.cpp constant.numeric.decimal.cpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ")", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.parens.cpp punctuation.section.parens.end.bracket.round.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "puts", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.function.call.cpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": "(", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.begin.bracket.round.function.call.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\"", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.begin.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "\\n", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp constant.character.escape.cpp", + "r": { + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #FF0000", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "constant.character: #569CD6" + } + }, + { + "c": "*************************************************", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "\"", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp punctuation.definition.string.end.cpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": ")", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.end.bracket.round.function.call.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "return", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.control.return.cpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": " ", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "0", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.numeric.decimal.cpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ";", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "}", + "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.block.end.bracket.curly.function.definition.cpp", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", diff --git a/extensions/csharp/package.json b/extensions/csharp/package.json index 3e2925282e2..3841eabd132 100644 --- a/extensions/csharp/package.json +++ b/extensions/csharp/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "0.10.x" }, diff --git a/extensions/csharp/test/colorize-results/test_cs.json b/extensions/csharp/test/colorize-results/test_cs.json index 1fc73fb341c..dbbe61ef3c6 100644 --- a/extensions/csharp/test/colorize-results/test_cs.json +++ b/extensions/csharp/test/colorize-results/test_cs.json @@ -3,11 +3,11 @@ "c": "using", "t": "source.cs keyword.other.using.cs", "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", + "dark_plus": "keyword.other.using: #C586C0", + "light_plus": "keyword.other.using: #AF00DB", "dark_vs": "keyword: #569CD6", "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6" + "hc_black": "keyword.other.using: #C586C0" } }, { diff --git a/extensions/css-language-features/.vscode/launch.json b/extensions/css-language-features/.vscode/launch.json index d6393141c5d..4f7166e6dce 100644 --- a/extensions/css-language-features/.vscode/launch.json +++ b/extensions/css-language-features/.vscode/launch.json @@ -23,8 +23,7 @@ "outFiles": [ "${workspaceFolder}/client/out/**/*.js" ], - "smartStep": true, - "preLaunchTask": "npm: compile" + "smartStep": true }, { "name": "Launch Tests", @@ -39,8 +38,7 @@ "sourceMaps": true, "outFiles": [ "${workspaceFolder}/client/out/test/**/*.js" - ], - "preLaunchTask": "npm: compile" + ] }, { "name": "Attach Language Server", diff --git a/extensions/css-language-features/.vscode/settings.json b/extensions/css-language-features/.vscode/settings.json new file mode 100644 index 00000000000..5b30e2983c2 --- /dev/null +++ b/extensions/css-language-features/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "prettier.semi": true, + "prettier.singleQuote": true, + "prettier.printWidth": 120, +} \ No newline at end of file diff --git a/extensions/css-language-features/client/src/cssMain.ts b/extensions/css-language-features/client/src/cssMain.ts index 6e0f2eb77c7..ee8c9973d3a 100644 --- a/extensions/css-language-features/client/src/cssMain.ts +++ b/extensions/css-language-features/client/src/cssMain.ts @@ -9,8 +9,9 @@ import * as fs from 'fs'; import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); -import { languages, window, commands, ExtensionContext, Range, Position, CompletionItem, CompletionItemKind, TextEdit, SnippetString } from 'vscode'; +import { languages, window, commands, ExtensionContext, Range, Position, CompletionItem, CompletionItemKind, TextEdit, SnippetString, workspace } from 'vscode'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, Disposable } from 'vscode-languageclient'; +import { getCustomDataPathsInAllWorkspaces, getCustomDataPathsFromAllExtensions } from './customData'; // this method is called when vs code is activated export function activate(context: ExtensionContext) { @@ -30,6 +31,11 @@ export function activate(context: ExtensionContext) { let documentSelector = ['css', 'scss', 'less']; + let dataPaths = [ + ...getCustomDataPathsInAllWorkspaces(workspace.workspaceFolders), + ...getCustomDataPathsFromAllExtensions() + ]; + // Options to control the language client let clientOptions: LanguageClientOptions = { documentSelector, @@ -37,6 +43,7 @@ export function activate(context: ExtensionContext) { configurationSection: ['css', 'scss', 'less'] }, initializationOptions: { + dataPaths } }; diff --git a/extensions/css-language-features/client/src/customData.ts b/extensions/css-language-features/client/src/customData.ts new file mode 100644 index 00000000000..b812b133ddc --- /dev/null +++ b/extensions/css-language-features/client/src/customData.ts @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from 'path'; +import { workspace, WorkspaceFolder, extensions } from 'vscode'; + +interface ExperimentalConfig { + experimental?: { + customData?: string[]; + }; +} + +export function getCustomDataPathsInAllWorkspaces(workspaceFolders: WorkspaceFolder[] | undefined): string[] { + const dataPaths: string[] = []; + + if (!workspaceFolders) { + return dataPaths; + } + + workspaceFolders.forEach(wf => { + const allCssConfig = workspace.getConfiguration(undefined, wf.uri); + const wfCSSConfig = allCssConfig.inspect('css'); + if ( + wfCSSConfig && + wfCSSConfig.workspaceFolderValue && + wfCSSConfig.workspaceFolderValue.experimental && + wfCSSConfig.workspaceFolderValue.experimental.customData + ) { + const customData = wfCSSConfig.workspaceFolderValue.experimental.customData; + if (Array.isArray(customData)) { + customData.forEach(t => { + if (typeof t === 'string') { + dataPaths.push(path.resolve(wf.uri.fsPath, t)); + } + }); + } + } + }); + + return dataPaths; +} + +export function getCustomDataPathsFromAllExtensions(): string[] { + const dataPaths: string[] = []; + + for (const extension of extensions.all) { + const contributes = extension.packageJSON && extension.packageJSON.contributes; + + if (contributes && contributes.css && contributes.css.experimental.customData && Array.isArray(contributes.css.experimental.customData)) { + const relativePaths: string[] = contributes.css.experimental.customData; + relativePaths.forEach(rp => { + dataPaths.push(path.resolve(extension.extensionPath, rp)); + }); + } + } + + return dataPaths; +} diff --git a/extensions/css-language-features/client/src/typings/ref.d.ts b/extensions/css-language-features/client/src/typings/ref.d.ts index 9c1a5df18ed..de602d3f8d6 100644 --- a/extensions/css-language-features/client/src/typings/ref.d.ts +++ b/extensions/css-language-features/client/src/typings/ref.d.ts @@ -2,5 +2,5 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - /// +/// diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json index e6f71ff0260..be663d36b7b 100644 --- a/extensions/css-language-features/package.json +++ b/extensions/css-language-features/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "^1.29.0" }, @@ -15,6 +16,7 @@ "onCommand:_css.applyCodeAction" ], "main": "./client/out/cssMain", + "enableProposedApi": true, "scripts": { "compile": "gulp compile-extension:css-language-features-client compile-extension:css-language-features-server", "watch": "gulp watch-extension:css-language-features-client watch-extension:css-language-features-server", @@ -32,6 +34,21 @@ "id": "css", "title": "%css.title%", "properties": { + "css.experimental.customData": { + "type": "array", + "description": "A list of JSON file paths that define custom CSS data that loads custom properties, at directives, pseudo classes / elements.", + "default": [], + "items": { + "type": "string" + }, + "scope": "resource" + }, + "css.completion.triggerPropertyValueCompletion": { + "type": "boolean", + "scope": "resource", + "default": true, + "description": "%css.completion.triggerPropertyValueCompletion.desc%" + }, "css.validate": { "type": "boolean", "scope": "resource", @@ -713,14 +730,20 @@ } } } + ], + "jsonValidation": [ + { + "fileMatch": "*.css-data.json", + "url": "https://raw.githubusercontent.com/Microsoft/vscode-css-languageservice/master/docs/customData.schema.json" + } ] }, "dependencies": { - "vscode-languageclient": "^5.1.0", - "vscode-nls": "^4.0.0" + "vscode-languageclient": "^5.3.0-next.6", + "vscode-nls": "^4.1.1" }, "devDependencies": { - "@types/node": "^8.10.25", + "@types/node": "^10.14.8", "mocha": "^5.2.0" } } diff --git a/extensions/css-language-features/package.nls.json b/extensions/css-language-features/package.nls.json index f136700f806..3e890bfd9bd 100644 --- a/extensions/css-language-features/package.nls.json +++ b/extensions/css-language-features/package.nls.json @@ -2,6 +2,7 @@ "displayName": "CSS Language Features", "description": "Provides rich language support for CSS, LESS and SCSS files.", "css.title": "CSS", + "css.completion.triggerPropertyValueCompletion.desc": "By default, VS Code triggers property value completion after selecting a CSS property. Use this setting to disable this behavior.", "css.lint.argumentsInColorFunction.desc": "Invalid number of parameters.", "css.lint.boxModel.desc": "Do not use `width` or `height` when using `padding` or `border`.", "css.lint.compatibleVendorPrefixes.desc": "When using a vendor-specific prefix make sure to also include all other vendor-specific properties.", @@ -72,4 +73,4 @@ "css.colorDecorators.enable.deprecationMessage": "The setting `css.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`.", "scss.colorDecorators.enable.deprecationMessage": "The setting `scss.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`.", "less.colorDecorators.enable.deprecationMessage": "The setting `less.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`." -} \ No newline at end of file +} diff --git a/extensions/css-language-features/server/extension.webpack.config.js b/extensions/css-language-features/server/extension.webpack.config.js index 17dc2d39e34..68b850b3773 100644 --- a/extensions/css-language-features/server/extension.webpack.config.js +++ b/extensions/css-language-features/server/extension.webpack.config.js @@ -9,7 +9,6 @@ const withDefaults = require('../../shared.webpack.config'); const path = require('path'); -var webpack = require('webpack'); module.exports = withDefaults({ context: path.join(__dirname), @@ -19,12 +18,5 @@ module.exports = withDefaults({ output: { filename: 'cssServerMain.js', path: path.join(__dirname, 'dist') - }, - plugins: [ - new webpack.NormalModuleReplacementPlugin( - /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, - require.resolve('./build/filesFillIn') - ), - new webpack.IgnorePlugin(/vertx/) - ], + } }); diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index 28f60c966d7..c6e8600d2ae 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -9,15 +9,15 @@ }, "main": "./out/cssServerMain", "dependencies": { - "vscode-css-languageservice": "^3.0.13-next.3", - "vscode-languageserver": "^5.1.0" + "vscode-css-languageservice": "^4.0.3-next.1", + "vscode-languageserver": "^5.3.0-next.8" }, "devDependencies": { "@types/mocha": "2.2.33", - "@types/node": "^8.10.25", - "glob": "^7.1.2", - "mocha": "^5.2.0", - "mocha-junit-reporter": "^1.17.0", + "@types/node": "^10.14.8", + "glob": "^7.1.4", + "mocha": "^6.1.4", + "mocha-junit-reporter": "^1.23.0", "mocha-multi-reporters": "^1.1.7" }, "scripts": { diff --git a/extensions/css-language-features/server/src/cssServerMain.ts b/extensions/css-language-features/server/src/cssServerMain.ts index 8c516fb8598..0bfd886c310 100644 --- a/extensions/css-language-features/server/src/cssServerMain.ts +++ b/extensions/css-language-features/server/src/cssServerMain.ts @@ -7,13 +7,15 @@ import { createConnection, IConnection, TextDocuments, InitializeParams, InitializeResult, ServerCapabilities, ConfigurationRequest, WorkspaceFolder } from 'vscode-languageserver'; import URI from 'vscode-uri'; -import { TextDocument, CompletionList } from 'vscode-languageserver-types'; +import { TextDocument, CompletionList, Position } from 'vscode-languageserver-types'; +import { stat as fsStat } from 'fs'; -import { getCSSLanguageService, getSCSSLanguageService, getLESSLanguageService, LanguageSettings, LanguageService, Stylesheet } from 'vscode-css-languageservice'; +import { getCSSLanguageService, getSCSSLanguageService, getLESSLanguageService, LanguageSettings, LanguageService, Stylesheet, FileSystemProvider, FileType } from 'vscode-css-languageservice'; import { getLanguageModelCache } from './languageModelCache'; import { getPathCompletionParticipant } from './pathCompletion'; -import { formatError, runSafe } from './utils/runner'; +import { formatError, runSafe, runSafeAsync } from './utils/runner'; import { getDocumentContext } from './utils/documentContext'; +import { getDataProviders } from './customData'; export interface Settings { css: LanguageSettings; @@ -31,8 +33,7 @@ process.on('unhandledRejection', (e: any) => { connection.console.error(formatError(`Unhandled exception`, e)); }); -// Create a simple text document manager. The text document manager -// supports full document sync only +// Create a text document manager. const documents: TextDocuments = new TextDocuments(); // Make the text document manager listen on the connection // for open, change and close text document events @@ -50,6 +51,47 @@ let scopedSettingsSupport = false; let foldingRangeLimit = Number.MAX_VALUE; let workspaceFolders: WorkspaceFolder[]; +const languageServices: { [id: string]: LanguageService } = {}; + +const fileSystemProvider: FileSystemProvider = { + stat(documentUri: string) { + const filePath = URI.parse(documentUri).fsPath; + + return new Promise((c, e) => { + fsStat(filePath, (err, stats) => { + if (err) { + if (err.code === 'ENOENT') { + return c({ + type: FileType.Unknown, + ctime: -1, + mtime: -1, + size: -1 + }); + } else { + return e(err); + } + } + + let type = FileType.Unknown; + if (stats.isFile()) { + type = FileType.File; + } else if (stats.isDirectory) { + type = FileType.Directory; + } else if (stats.isSymbolicLink) { + type = FileType.SymbolicLink; + } + + c({ + type, + ctime: stats.ctime.getTime(), + mtime: stats.mtime.getTime(), + size: stats.size + }); + }); + }); + } +}; + // After the server has started the client sends an initialize request. The server receives // in the passed params the rootPath of the workspace plus the client capabilities. connection.onInitialize((params: InitializeParams): InitializeResult => { @@ -61,6 +103,9 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { } } + const dataPaths: string[] = params.initializationOptions.dataPaths; + const customDataProviders = getDataProviders(dataPaths); + function getClientCapability(name: string, def: T) { const keys = name.split('.'); let c: any = params.capabilities; @@ -76,6 +121,10 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { scopedSettingsSupport = !!getClientCapability('workspace.configuration', false); foldingRangeLimit = getClientCapability('textDocument.foldingRange.rangeLimit', Number.MAX_VALUE); + languageServices.css = getCSSLanguageService({ customDataProviders, fileSystemProvider, clientCapabilities: params.capabilities }); + languageServices.scss = getSCSSLanguageService({ customDataProviders, fileSystemProvider, clientCapabilities: params.capabilities }); + languageServices.less = getLESSLanguageService({ customDataProviders, fileSystemProvider, clientCapabilities: params.capabilities }); + const capabilities: ServerCapabilities = { // Tell the client that the server works in FULL text document sync mode textDocumentSync: documents.syncKind, @@ -91,17 +140,12 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { codeActionProvider: true, renameProvider: true, colorProvider: {}, - foldingRangeProvider: true + foldingRangeProvider: true, + selectionRangeProvider: true }; return { capabilities }; }); -const languageServices: { [id: string]: LanguageService } = { - css: getCSSLanguageService(), - scss: getSCSSLanguageService(), - less: getLESSLanguageService() -}; - function getLanguageService(document: TextDocument) { let service = languageServices[document.languageId]; if (!service) { @@ -253,13 +297,13 @@ connection.onDocumentHighlight((documentHighlightParams, token) => { }); -connection.onDocumentLinks((documentLinkParams, token) => { - return runSafe(() => { +connection.onDocumentLinks(async (documentLinkParams, token) => { + return runSafeAsync(async () => { const document = documents.get(documentLinkParams.textDocument.uri); if (document) { const documentContext = getDocumentContext(document.uri, workspaceFolders); const stylesheet = stylesheets.get(document); - return getLanguageService(document).findDocumentLinks(document, stylesheet, documentContext); + return await getLanguageService(document).findDocumentLinks2(document, stylesheet, documentContext); } return []; }, [], `Error while computing document links for ${documentLinkParams.textDocument.uri}`, token); @@ -331,5 +375,19 @@ connection.onFoldingRanges((params, token) => { }, null, `Error while computing folding ranges for ${params.textDocument.uri}`, token); }); +connection.onSelectionRanges((params, token) => { + return runSafe(() => { + const document = documents.get(params.textDocument.uri); + const positions: Position[] = params.positions; + + if (document) { + const stylesheet = stylesheets.get(document); + return getLanguageService(document).getSelectionRanges(document, positions, stylesheet); + } + return []; + }, [], `Error while computing selection ranges for ${params.textDocument.uri}`, token); +}); + + // Listen on the connection connection.listen(); \ No newline at end of file diff --git a/extensions/css-language-features/server/src/customData.ts b/extensions/css-language-features/server/src/customData.ts new file mode 100644 index 00000000000..f173d884a2b --- /dev/null +++ b/extensions/css-language-features/server/src/customData.ts @@ -0,0 +1,50 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CSSDataV1, ICSSDataProvider } from 'vscode-css-languageservice'; +import * as fs from 'fs'; + +export function getDataProviders(dataPaths: string[]): ICSSDataProvider[] { + const providers = dataPaths.map(p => { + if (fs.existsSync(p)) { + const data = parseCSSData(fs.readFileSync(p, 'utf-8')); + return { + provideProperties: () => data.properties || [], + provideAtDirectives: () => data.atDirectives || [], + providePseudoClasses: () => data.pseudoClasses || [], + providePseudoElements: () => data.pseudoElements || [] + }; + } else { + return { + provideProperties: () => [], + provideAtDirectives: () => [], + providePseudoClasses: () => [], + providePseudoElements: () => [] + }; + } + }); + + return providers; +} + +function parseCSSData(source: string): CSSDataV1 { + let rawData: any; + + try { + rawData = JSON.parse(source); + } catch (err) { + return { + version: 1 + }; + } + + return { + version: 1, + properties: rawData.properties || [], + atDirectives: rawData.atDirectives || [], + pseudoClasses: rawData.pseudoClasses || [], + pseudoElements: rawData.pseudoElements || [] + }; +} diff --git a/extensions/css-language-features/server/src/pathCompletion.ts b/extensions/css-language-features/server/src/pathCompletion.ts index 4d988a52da9..aafed82b513 100644 --- a/extensions/css-language-features/server/src/pathCompletion.ts +++ b/extensions/css-language-features/server/src/pathCompletion.ts @@ -154,10 +154,10 @@ function pathToReplaceRange(valueBeforeCursor: string, fullValue: string, fullVa const valueAfterLastSlash = fullValue.slice(lastIndexOfSlash + 1); const startPos = shiftPosition(fullValueRange.end, -valueAfterLastSlash.length); // If whitespace exists, replace until it - const whiteSpaceIndex = valueAfterLastSlash.indexOf(' '); + const whitespaceIndex = valueAfterLastSlash.indexOf(' '); let endPos; - if (whiteSpaceIndex !== -1) { - endPos = shiftPosition(startPos, whiteSpaceIndex); + if (whitespaceIndex !== -1) { + endPos = shiftPosition(startPos, whitespaceIndex); } else { endPos = fullValueRange.end; } diff --git a/extensions/css-language-features/server/src/test/links.test.ts b/extensions/css-language-features/server/src/test/links.test.ts new file mode 100644 index 00000000000..bce7a11bc8a --- /dev/null +++ b/extensions/css-language-features/server/src/test/links.test.ts @@ -0,0 +1,79 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import 'mocha'; +import * as assert from 'assert'; +import Uri from 'vscode-uri'; +import { resolve } from 'path'; +import { TextDocument, DocumentLink } from 'vscode-languageserver-types'; +import { WorkspaceFolder } from 'vscode-languageserver-protocol'; +import { getCSSLanguageService } from 'vscode-css-languageservice'; +import { getDocumentContext } from '../utils/documentContext'; + +export interface ItemDescription { + offset: number; + value: string; + target: string; +} + +suite('Links', () => { + const cssLanguageService = getCSSLanguageService(); + + let assertLink = function (links: DocumentLink[], expected: ItemDescription, document: TextDocument) { + let matches = links.filter(link => { + return document.offsetAt(link.range.start) === expected.offset; + }); + + assert.equal(matches.length, 1, `${expected.offset} should only existing once: Actual: ${links.map(l => document.offsetAt(l.range.start)).join(', ')}`); + let match = matches[0]; + assert.equal(document.getText(match.range), expected.value); + assert.equal(match.target, expected.target); + }; + + function assertLinks(value: string, expected: ItemDescription[], testUri: string, workspaceFolders?: WorkspaceFolder[], lang: string = 'css'): void { + const offset = value.indexOf('|'); + value = value.substr(0, offset) + value.substr(offset + 1); + + const document = TextDocument.create(testUri, lang, 0, value); + + if (!workspaceFolders) { + workspaceFolders = [{ name: 'x', uri: testUri.substr(0, testUri.lastIndexOf('/')) }]; + } + + const context = getDocumentContext(testUri, workspaceFolders); + + const stylesheet = cssLanguageService.parseStylesheet(document); + let links = cssLanguageService.findDocumentLinks(document, stylesheet, context)!; + + assert.equal(links.length, expected.length); + + for (let item of expected) { + assertLink(links, item, document); + } + } + + function getTestResource(path: string) { + return Uri.file(resolve(__dirname, '../../test/linksTestFixtures', path)).toString(); + } + + test('url links', function () { + + let testUri = getTestResource('about.css'); + let folders = [{ name: 'x', uri: getTestResource('') }]; + + assertLinks('html { background-image: url("hello.html|")', + [{ offset: 29, value: '"hello.html"', target: getTestResource('hello.html') }], testUri, folders + ); + }); + + test('node module resolving', function () { + + let testUri = getTestResource('about.css'); + let folders = [{ name: 'x', uri: getTestResource('') }]; + + assertLinks('html { background-image: url("~foo/hello.html|")', + [{ offset: 29, value: '"~foo/hello.html"', target: getTestResource('node_modules/foo/hello.html') }], testUri, folders + ); + }); +}); \ No newline at end of file diff --git a/extensions/css-language-features/server/src/utils/documentContext.ts b/extensions/css-language-features/server/src/utils/documentContext.ts index 9858ca84367..494ff395e9d 100644 --- a/extensions/css-language-features/server/src/utils/documentContext.ts +++ b/extensions/css-language-features/server/src/utils/documentContext.ts @@ -7,6 +7,27 @@ import { DocumentContext } from 'vscode-css-languageservice'; import { endsWith, startsWith } from '../utils/strings'; import * as url from 'url'; import { WorkspaceFolder } from 'vscode-languageserver'; +import URI from 'vscode-uri'; +import { join, dirname } from 'path'; +import { existsSync } from 'fs'; + +function getModuleNameFromPath(path: string) { + // If a scoped module (starts with @) then get up until second instance of '/', otherwise get until first isntance of '/' + if (path[0] === '@') { + return path.substring(0, path.indexOf('/', path.indexOf('/') + 1)); + } + return path.substring(0, path.indexOf('/')); +} + +function resolvePathToModule(_moduleName: string, _relativeTo: string): string | undefined { + // resolve the module relative to the document. We can't use `require` here as the code is webpacked. + const documentFolder = dirname(URI.parse(_relativeTo).fsPath); + const packPath = join(documentFolder, 'node_modules', _moduleName, 'package.json'); + if (existsSync(packPath)) { + return URI.file(packPath).toString(); + } + return undefined; +} export function getDocumentContext(documentUri: string, workspaceFolders: WorkspaceFolder[]): DocumentContext { function getRootFolder(): string | undefined { @@ -32,6 +53,22 @@ export function getDocumentContext(documentUri: string, workspaceFolders: Worksp } } } + // Following [css-loader](https://github.com/webpack-contrib/css-loader#url) + // and [sass-loader's](https://github.com/webpack-contrib/sass-loader#imports) + // convention, if an import path starts with ~ then use node module resolution + // *unless* it starts with "~/" as this refers to the user's home directory. + if (ref[0] === '~' && ref[1] !== '/') { + ref = ref.substring(1); + if (startsWith(base, 'file://')) { + const moduleName = getModuleNameFromPath(ref); + const modulePath = resolvePathToModule(moduleName, base); + if (modulePath) { + const pathWithinModule = ref.substring(moduleName.length + 1); + return url.resolve(modulePath, pathWithinModule); + } + } + + } return url.resolve(base, ref); }, }; diff --git a/extensions/css-language-features/server/src/utils/runner.ts b/extensions/css-language-features/server/src/utils/runner.ts index df024167dab..98a7a96f9aa 100644 --- a/extensions/css-language-features/server/src/utils/runner.ts +++ b/extensions/css-language-features/server/src/utils/runner.ts @@ -17,6 +17,27 @@ export function formatError(message: string, err: any): string { return message; } +export function runSafeAsync(func: () => Thenable, errorVal: T, errorMessage: string, token: CancellationToken): Thenable> { + return new Promise>((resolve) => { + setImmediate(() => { + if (token.isCancellationRequested) { + resolve(cancelValue()); + } + return func().then(result => { + if (token.isCancellationRequested) { + resolve(cancelValue()); + return; + } else { + resolve(result); + } + }, e => { + console.error(formatError(errorMessage, e)); + resolve(errorVal); + }); + }); + }); +} + export function runSafe(func: () => T, errorVal: T, errorMessage: string, token: CancellationToken): Thenable> { return new Promise>((resolve) => { setImmediate(() => { diff --git a/extensions/css-language-features/server/test/linksTestFixtures/.gitignore b/extensions/css-language-features/server/test/linksTestFixtures/.gitignore new file mode 100644 index 00000000000..d591cdfd50a --- /dev/null +++ b/extensions/css-language-features/server/test/linksTestFixtures/.gitignore @@ -0,0 +1 @@ +!/node_modules \ No newline at end of file diff --git a/extensions/css-language-features/server/test/linksTestFixtures/node_modules/foo/package.json b/extensions/css-language-features/server/test/linksTestFixtures/node_modules/foo/package.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index 30c2fb6c62f..d93eec392c7 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -7,16 +7,45 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.33.tgz#d79a0061ec270379f4d9e225f4096fb436669def" integrity sha1-15oAYewnA3n02eIl9AlvtDZmne8= -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== + +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -35,32 +64,78 @@ browser-stdout@1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +chalk@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= -debug@3.1.0, debug@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: - ms "2.0.0" + ms "^2.1.1" debug@^2.2.0: version "2.6.9" @@ -69,25 +144,143 @@ debug@^2.2.0: dependencies: ms "2.0.0" +debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +define-properties@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== -escape-string-regexp@1.0.5: +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + dependencies: + once "^1.4.0" + +es-abstract@^1.5.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" + integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-keys "^1.0.12" + +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +flat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + dependencies: + is-buffer "~2.0.3" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -glob@7.1.2, glob@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.4: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -106,10 +299,22 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== inflight@^1.0.4: version "1.0.6" @@ -124,16 +329,114 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + is-buffer@~1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-buffer@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" + integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== + +is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-yaml@3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" + integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + dependencies: + invert-kv "^2.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + lodash@^4.16.4: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" integrity sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg== +lodash@^4.17.11: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== + +log-symbols@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + md5@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" @@ -143,6 +446,20 @@ md5@^2.1.0: crypt "~0.0.1" is-buffer "~1.1.1" +mem@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" + integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== + dependencies: + map-age-cleaner "^0.1.1" + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" + +mimic-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -162,10 +479,10 @@ mkdirp@0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" -mocha-junit-reporter@^1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.17.0.tgz#2e5149ed40fc5d2e3ca71e42db5ab1fec9c6d85c" - integrity sha1-LlFJ7UD8XS48px5C21qx/snG2Fw= +mocha-junit-reporter@^1.23.0: + version "1.23.0" + resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.23.0.tgz#c5ad7f10b5aa9a7cc6e169b6bf15baf2700266ca" + integrity sha512-pmpnEO4iDTmLfrT2RKqPsc5relG4crnDSGmXPuGogdda27A7kLujDNJV4EbTbXlVBCZXggN9rQYPEWMkOv4AAA== dependencies: debug "^2.2.0" md5 "^2.1.0" @@ -181,40 +498,251 @@ mocha-multi-reporters@^1.1.7: debug "^3.1.0" lodash "^4.16.4" -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== +mocha@^6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.1.4.tgz#e35fada242d5434a7e163d555c705f6875951640" + integrity sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg== dependencies: + ansi-colors "3.2.3" browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" + debug "3.2.6" diff "3.5.0" escape-string-regexp "1.0.5" - glob "7.1.2" + find-up "3.0.0" + glob "7.1.3" growl "1.10.5" - he "1.1.1" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" minimatch "3.0.4" mkdirp "0.5.1" - supports-color "5.4.0" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.2.2" + yargs-parser "13.0.0" + yargs-unparser "1.5.0" ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -once@^1.3.0: +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +object-keys@^1.0.11, object-keys@^1.0.12: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" +os-locale@^3.0.0, os-locale@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== + +p-limit@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" + integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +semver@^5.5.0, semver@^5.7.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" @@ -222,57 +750,120 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -supports-color@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-json-comments@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== dependencies: has-flag "^3.0.0" -vscode-css-languageservice@^3.0.13-next.3: - version "3.0.13-next.3" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-3.0.13-next.3.tgz#b9e6f253cace52fbb749d2fe194ae4b196f3543e" - integrity sha512-7+7JddZRt8zFRLbqygxJw+GHtbQ5o2YvgEFvi4ixvbUAX6KlY3Yw6CgUUbg9dmBla7h+GbtoDjwiLFV6Oy+SBQ== +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: - vscode-languageserver-types "^3.13.0" - vscode-nls "^4.0.0" + has-flag "^3.0.0" -vscode-jsonrpc@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" - integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== - -vscode-languageserver-protocol@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz#710d8e42119bb3affb1416e1e104bd6b4d503595" - integrity sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg== +vscode-css-languageservice@^4.0.3-next.1: + version "4.0.3-next.1" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.1.tgz#e89d01ce0d79b3e6c2642f5e3ad73cb8160d38d9" + integrity sha512-Zrm5TeraVUJ8vRikWhFt259dQu+WK+Ie3K5UA8BB4kqcanoM+1mcnIt8fPkTXlZLbiEWElrkJ9yuYbDNkufeBg== dependencies: - vscode-jsonrpc "^4.0.0" - vscode-languageserver-types "3.13.0" + vscode-languageserver-types "^3.15.0-next.2" + vscode-nls "^4.1.1" + vscode-uri "^2.0.3" -vscode-languageserver-types@3.13.0, vscode-languageserver-types@^3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz#b704b024cef059f7b326611c99b9c8753c0a18b4" - integrity sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA== +vscode-jsonrpc@^4.1.0-next.2: + version "4.1.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" + integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== -vscode-languageserver@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.1.0.tgz#012a28f154cc7a848c443d217894942e4c3eeb39" - integrity sha512-CIsrgx2Y5VHS317g/HwkSTWYBIQmy0DwEyZPmB2pEpVOhYFwVsYpbiJwHIIyLQsQtmRaO4eA2xM8KPjNSdXpBw== +vscode-languageserver-protocol@^3.15.0-next.6: + version "3.15.0-next.6" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" + integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== dependencies: - vscode-languageserver-protocol "3.13.0" + vscode-jsonrpc "^4.1.0-next.2" + vscode-languageserver-types "^3.15.0-next.2" + +vscode-languageserver-types@^3.15.0-next.2: + version "3.15.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" + integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== + +vscode-languageserver@^5.3.0-next.8: + version "5.3.0-next.8" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.3.0-next.8.tgz#12a4adf60374dbb93e153e08bdca5525f9b2029f" + integrity sha512-6vUb96wsRfrFqndril3gct/FBCSc24OxFZ2iz7kuEuXvLaIcEVOcSZIqQK8oFN7PdbAIaa9nnIpKSy4Yd15cIw== + dependencies: + vscode-languageserver-protocol "^3.15.0-next.6" + vscode-textbuffer "^1.0.0" vscode-uri "^1.0.6" -vscode-nls@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002" - integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw== +vscode-nls@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" + integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== + +vscode-textbuffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/vscode-textbuffer/-/vscode-textbuffer-1.0.0.tgz#1faee638c8e0e4131c8d5c353993a1874acda086" + integrity sha512-zPaHo4urgpwsm+PrJWfNakolRpryNja18SUip/qIIsfhuEqEIPEXMxHOlFPjvDC4JgTaimkncNW7UMXRJTY6ow== vscode-uri@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.6.tgz#6b8f141b0bbc44ad7b07e94f82f168ac7608ad4d" integrity sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww== +vscode-uri@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543" + integrity sha512-4D3DI3F4uRy09WNtDGD93H9q034OHImxiIcSq664Hq1Y1AScehlP3qqZyTkX/RWxeu0MRMHGkrxYqm2qlDF/aw== + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@1.3.1, which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -282,3 +873,76 @@ xml@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= + +"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yargs-parser@13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.0.0.tgz#3fc44f3e76a8bdb1cc3602e860108602e5ccde8b" + integrity sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" + integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^13.0.0: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-unparser@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.5.0.tgz#f2bb2a7e83cbc87bb95c8e572828a06c9add6e0d" + integrity sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw== + dependencies: + flat "^4.1.0" + lodash "^4.17.11" + yargs "^12.0.5" + +yargs@13.2.2: + version "13.2.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.2.tgz#0c101f580ae95cea7f39d927e7770e3fdc97f993" + integrity sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA== + dependencies: + cliui "^4.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + os-locale "^3.1.0" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.0.0" + +yargs@^12.0.5: + version "12.0.5" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" + integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== + dependencies: + cliui "^4.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^1.0.1" + os-locale "^3.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1 || ^4.0.0" + yargs-parser "^11.1.1" diff --git a/extensions/css-language-features/yarn.lock b/extensions/css-language-features/yarn.lock index d626f86f433..48f16a42fe5 100644 --- a/extensions/css-language-features/yarn.lock +++ b/extensions/css-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== balanced-match@^1.0.0: version "1.0.0" @@ -162,36 +162,36 @@ supports-color@5.4.0: dependencies: has-flag "^3.0.0" -vscode-jsonrpc@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" - integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== +vscode-jsonrpc@^4.1.0-next.2: + version "4.1.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" + integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== -vscode-languageclient@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.1.0.tgz#650ab0dc9fd0daaade058a8471aaff5bc3f9580e" - integrity sha512-Z95Kps8UqD4o17HE3uCkZuvenOsxHVH46dKmaGVpGixEFZigPaVuVxLM/JWeIY9aRenoC0ZD9CK1O7L4jpffKg== +vscode-languageclient@^5.3.0-next.6: + version "5.3.0-next.6" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.3.0-next.6.tgz#35e74882781158e8b111911c0953869d3df08777" + integrity sha512-DxT8+gkenjCjJV6ArcP75/AQfx6HP6m6kHIbacPCpffMeoE1YMLKj6ZixA9J87yr0fMtBmqumLmDeGe7MIF2bw== dependencies: semver "^5.5.0" - vscode-languageserver-protocol "3.13.0" + vscode-languageserver-protocol "^3.15.0-next.6" -vscode-languageserver-protocol@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz#710d8e42119bb3affb1416e1e104bd6b4d503595" - integrity sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg== +vscode-languageserver-protocol@^3.15.0-next.6: + version "3.15.0-next.6" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" + integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== dependencies: - vscode-jsonrpc "^4.0.0" - vscode-languageserver-types "3.13.0" + vscode-jsonrpc "^4.1.0-next.2" + vscode-languageserver-types "^3.15.0-next.2" -vscode-languageserver-types@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz#b704b024cef059f7b326611c99b9c8753c0a18b4" - integrity sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA== +vscode-languageserver-types@^3.15.0-next.2: + version "3.15.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" + integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== -vscode-nls@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002" - integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw== +vscode-nls@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" + integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== wrappy@1: version "1.0.2" diff --git a/extensions/css/.vscodeignore b/extensions/css/.vscodeignore index 0a622e7e300..52ebcbd68b2 100644 --- a/extensions/css/.vscodeignore +++ b/extensions/css/.vscodeignore @@ -1,2 +1,3 @@ test/** cgmanifest.json +.vscode \ No newline at end of file diff --git a/extensions/css/cgmanifest.json b/extensions/css/cgmanifest.json index 182b3ec7a66..a47fef967ec 100644 --- a/extensions/css/cgmanifest.json +++ b/extensions/css/cgmanifest.json @@ -4,14 +4,14 @@ "component": { "type": "git", "git": { - "name": "atom/language-css", - "repositoryUrl": "https://github.com/atom/language-css", - "commitHash": "7e06c88b89218fe6e8eba77fb674152f1cea0b10" + "name": "octref/language-css", + "repositoryUrl": "https://github.com/octref/language-css", + "commitHash": "377734aad976be88a425aab5667784f3f71ea7e5" } }, "license": "MIT", - "description": "The file syntaxes/css.tmLanguage.json was derived from the Atom package https://github.com/atom/language-css which was originally converted from the TextMate bundle https://github.com/textmate/css.tmbundle.", - "version": "0.0.0" + "description": "The file syntaxes/css.tmLanguage.json was derived from https://github.com/octref/language-css which was derived from the Atom package https://github.com/atom/language-css which was originally converted from the TextMate bundle https://github.com/textmate/css.tmbundle.", + "version": "0.42.11" } ], "version": 1 diff --git a/extensions/css/package.json b/extensions/css/package.json index 13f737e92fc..117f759dd9d 100644 --- a/extensions/css/package.json +++ b/extensions/css/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "0.10.x" }, diff --git a/extensions/css/syntaxes/css.tmLanguage.json b/extensions/css/syntaxes/css.tmLanguage.json index 488c8f12c30..8dbdf1f7413 100644 --- a/extensions/css/syntaxes/css.tmLanguage.json +++ b/extensions/css/syntaxes/css.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/octref/language-css/commit/7e06c88b89218fe6e8eba77fb674152f1cea0b10", + "version": "https://github.com/octref/language-css/commit/377734aad976be88a425aab5667784f3f71ea7e5", "name": "CSS", "scopeName": "source.css", "patterns": [ @@ -606,8 +606,32 @@ ] }, { - "begin": "(?i)(?=@[\\w-]+(\\s|\\(|{|;|/\\*|$))", - "end": "(?<=}|;)(?!\\G)", + "begin": "(?i)(?=@[\\w-]+[^;]+;s*$)", + "end": "(?<=;)(?!\\G)", + "patterns": [ + { + "begin": "(?i)\\G(@)[\\w-]+", + "beginCaptures": { + "0": { + "name": "keyword.control.at-rule.css" + }, + "1": { + "name": "punctuation.definition.keyword.css" + } + }, + "end": ";", + "endCaptures": { + "0": { + "name": "punctuation.terminator.rule.css" + } + }, + "name": "meta.at-rule.header.css" + } + ] + }, + { + "begin": "(?i)(?=@[\\w-]+(\\s|\\(|{|/\\*|$))", + "end": "(?<=})(?!\\G)", "patterns": [ { "begin": "(?i)\\G(@)[\\w-]+", @@ -1397,7 +1421,7 @@ "property-names": { "patterns": [ { - "match": "(?xi) (?(); + + private hasFired = false; + private shellPid?: number; + private regexp: RegExp; + private disposables: vscode.Disposable[] = []; + + static start(session: vscode.DebugSession): ServerReadyDetector | undefined { + if (session.configuration.serverReadyAction) { + let detector = ServerReadyDetector.detectors.get(session); + if (!detector) { + detector = new ServerReadyDetector(session); + ServerReadyDetector.detectors.set(session, detector); + } + return detector; + } + return undefined; + } + + static stop(session: vscode.DebugSession): void { + let detector = ServerReadyDetector.detectors.get(session); + if (detector) { + ServerReadyDetector.detectors.delete(session); + detector.dispose(); + } + } + + static rememberShellPid(session: vscode.DebugSession, pid: number) { + let detector = ServerReadyDetector.detectors.get(session); + if (detector) { + detector.shellPid = pid; + } + } + + private constructor(private session: vscode.DebugSession) { + super(() => this.internalDispose()); + + this.regexp = new RegExp(session.configuration.serverReadyAction.pattern || PATTERN, 'i'); + } + + private internalDispose() { + this.disposables.forEach(d => d.dispose()); + this.disposables = []; + } + + async trackTerminals() { + + let terminals: vscode.Terminal[] = []; + + // either find the terminal where the debug is started with "runInTerminal" or use all terminals + for (let terminal of vscode.window.terminals) { + if (!this.shellPid || await terminal.processId === this.shellPid) { + terminals.push(terminal); + } + } + this.shellPid = undefined; + + terminals.forEach(terminal => { + this.disposables.push(terminal.onDidWriteData(s => { + this.detectPattern(s); + })); + }); + } + + detectPattern(s: string): void { + + if (!this.hasFired) { + const matches = this.regexp.exec(s); + if (matches && matches.length >= 1) { + this.openExternalWithString(this.session, matches.length > 1 ? matches[1] : ''); + this.hasFired = true; + this.internalDispose(); + } + } + } + + private openExternalWithString(session: vscode.DebugSession, captureString: string) { + + const args: ServerReadyAction = session.configuration.serverReadyAction; + const format = args.uriFormat || URI_FORMAT; + + if (captureString === '') { + // nothing captured by reg exp -> use the uriFormat as the target url without substitution + // verify that format does not contain '%s' + if (format.indexOf('%s') >= 0) { + const errMsg = localize('server.ready.nocapture.error', "Format uri ('{0}') uses a substitution placeholder but pattern did not capture anything.", format); + vscode.window.showErrorMessage(errMsg, { modal: true }).then(_ => undefined); + return; + } + captureString = format; + } else if (/^[0-9]+$/.test(captureString)) { + // looks like a port number -> use the uriFormat and substitute a single "%s" with the port + // verify that format only contains a single '%s' + const s = format.split('%s'); + if (s.length !== 2) { + const errMsg = localize('server.ready.placeholder.error', "Format uri ('{0}') must contain exactly one substitution placeholder.", format); + vscode.window.showErrorMessage(errMsg, { modal: true }).then(_ => undefined); + return; + } + captureString = util.format(format, captureString); + } else { + // use the string as is + } + + this.openExternalWithUri(session, captureString); + } + + private openExternalWithUri(session: vscode.DebugSession, uri: string) { + + const args: ServerReadyAction = session.configuration.serverReadyAction; + switch (args.action || 'openExternally') { + case 'openExternally': + vscode.env.openExternal(vscode.Uri.parse(uri)); + break; + case 'debugWithChrome': + + if (vscode.env.remoteName === 'wsl' || !!vscode.extensions.getExtension('msjsdiag.debugger-for-chrome')) { + vscode.debug.startDebugging(session.workspaceFolder, { + type: 'chrome', + name: 'Chrome Debug', + request: 'launch', + url: uri, + webRoot: args.webRoot || WEB_ROOT + }, session); + } else { + const errMsg = localize('server.ready.chrome.not.installed', "The action '{0}' requires the '{1}' extension.", 'debugWithChrome', 'Debugger for Chrome'); + vscode.window.showErrorMessage(errMsg, { modal: true }).then(_ => undefined); + } + break; + default: + // not supported + break; + } + } +} + +export function activate(context: vscode.ExtensionContext) { + + context.subscriptions.push(vscode.debug.onDidChangeActiveDebugSession(session => { + if (session && session.configuration.serverReadyAction) { + const detector = ServerReadyDetector.start(session); + if (detector) { + detector.trackTerminals(); + } + } + })); + + context.subscriptions.push(vscode.debug.onDidTerminateDebugSession(session => { + ServerReadyDetector.stop(session); + })); + + const trackers = new Set(); + + context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('*', { + resolveDebugConfiguration(_folder: vscode.WorkspaceFolder | undefined, debugConfiguration: vscode.DebugConfiguration) { + if (debugConfiguration.type && debugConfiguration.serverReadyAction) { + if (!trackers.has(debugConfiguration.type)) { + trackers.add(debugConfiguration.type); + startTrackerForType(context, debugConfiguration.type); + } + } + return debugConfiguration; + } + })); +} + +function startTrackerForType(context: vscode.ExtensionContext, type: string) { + + // scan debug console output for a PORT message + context.subscriptions.push(vscode.debug.registerDebugAdapterTrackerFactory(type, { + createDebugAdapterTracker(session: vscode.DebugSession) { + const detector = ServerReadyDetector.start(session); + if (detector) { + let runInTerminalRequestSeq: number | undefined; + return { + onDidSendMessage: m => { + if (m.type === 'event' && m.event === 'output' && m.body) { + switch (m.body.category) { + case 'console': + case 'stderr': + case 'stdout': + if (m.body.output) { + detector.detectPattern(m.body.output); + } + break; + default: + break; + } + } + if (m.type === 'request' && m.command === 'runInTerminal' && m.arguments) { + if (m.arguments.kind === 'integrated') { + runInTerminalRequestSeq = m.seq; // remember this to find matching response + } + } + }, + onWillReceiveMessage: m => { + if (runInTerminalRequestSeq && m.type === 'response' && m.command === 'runInTerminal' && m.body && runInTerminalRequestSeq === m.request_seq) { + runInTerminalRequestSeq = undefined; + ServerReadyDetector.rememberShellPid(session, m.body.shellProcessId); + } + } + }; + } + return undefined; + } + })); +} diff --git a/extensions/debug-server-ready/src/typings/ref.d.ts b/extensions/debug-server-ready/src/typings/ref.d.ts new file mode 100644 index 00000000000..954bab971e3 --- /dev/null +++ b/extensions/debug-server-ready/src/typings/ref.d.ts @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/// +/// +/// diff --git a/extensions/debug-server-ready/tsconfig.json b/extensions/debug-server-ready/tsconfig.json new file mode 100644 index 00000000000..f9b780a0e1c --- /dev/null +++ b/extensions/debug-server-ready/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../shared.tsconfig.json", + "compilerOptions": { + "outDir": "./out", + "downlevelIteration": true + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file diff --git a/extensions/debug-server-ready/yarn.lock b/extensions/debug-server-ready/yarn.lock new file mode 100644 index 00000000000..e6247e29255 --- /dev/null +++ b/extensions/debug-server-ready/yarn.lock @@ -0,0 +1,13 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== + +vscode-nls@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002" + integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw== diff --git a/extensions/docker/cgmanifest.json b/extensions/docker/cgmanifest.json index 844d3120d3c..dbbf43607ee 100644 --- a/extensions/docker/cgmanifest.json +++ b/extensions/docker/cgmanifest.json @@ -15,4 +15,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/docker/package.json b/extensions/docker/package.json index 41df24723fa..f5f2f795fc4 100644 --- a/extensions/docker/package.json +++ b/extensions/docker/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js moby/moby contrib/syntax/textmate/Docker.tmbundle/Syntaxes/Dockerfile.tmLanguage ./syntaxes/docker.tmLanguage.json" diff --git a/extensions/emmet/.vscode/launch.json b/extensions/emmet/.vscode/launch.json index 8a89122dafb..0b693f921ee 100644 --- a/extensions/emmet/.vscode/launch.json +++ b/extensions/emmet/.vscode/launch.json @@ -1,21 +1,31 @@ { - // Use IntelliSense to learn about possible Node.js debug attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "extensionHost", - "request": "launch", - "name": "Launch Extension", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "sourceMaps": true, - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ] - } - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible Node.js debug attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "extensionHost", + "request": "launch", + "name": "Launch Extension", + "runtimeExecutable": "${execPath}", + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "sourceMaps": true, + "outFiles": ["${workspaceFolder}/out/**/*.js"] + }, + { + "type": "extensionHost", + "request": "launch", + "name": "Launch Tests", + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/out/test", + "--disable-extensions", + "--skip-getting-started", + ], + "sourceMaps": true, + "outFiles": ["${workspaceFolder}/out/**/*.js"] + } + ] +} diff --git a/extensions/emmet/.vscodeignore b/extensions/emmet/.vscodeignore index 50d0ee883e6..573d91ebe6b 100644 --- a/extensions/emmet/.vscodeignore +++ b/extensions/emmet/.vscodeignore @@ -6,3 +6,4 @@ extension.webpack.config.js CONTRIBUTING.md cgmanifest.json yarn.lock +.vscode \ No newline at end of file diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 8733fbdb5c9..d88c3717ab3 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "^1.13.0" }, @@ -434,10 +435,12 @@ } }, "scripts": { - "compile": "gulp compile-extension:emmet" + "watch": "gulp watch-extension:emmet", + "compile": "gulp compile-extension:emmet", + "deps": "yarn add vscode-emmet-helper" }, "devDependencies": { - "@types/node": "8.0.33", + "@types/node": "^10.14.8", "mocha-junit-reporter": "^1.17.0", "mocha-multi-reporters": "^1.1.7", "vscode": "1.0.1" @@ -447,6 +450,7 @@ "@emmetio/html-matcher": "^0.3.3", "@emmetio/math-expression": "^0.1.1", "image-size": "^0.5.2", - "vscode-emmet-helper": "^1.2.12" + "vscode-emmet-helper": "^1.2.15", + "vscode-html-languageservice": "^3.0.3" } } diff --git a/extensions/emmet/src/abbreviationActions.ts b/extensions/emmet/src/abbreviationActions.ts index dbde660d9e5..9508d3a6a0b 100644 --- a/extensions/emmet/src/abbreviationActions.ts +++ b/extensions/emmet/src/abbreviationActions.ts @@ -7,8 +7,8 @@ import * as vscode from 'vscode'; import { Node, HtmlNode, Rule, Property, Stylesheet } from 'EmmetNode'; import { getEmmetHelper, getNode, getInnerRange, getMappingForIncludedLanguages, parseDocument, validate, getEmmetConfiguration, isStyleSheet, getEmmetMode, parsePartialStylesheet, isStyleAttribute, getEmbeddedCssNodeIfAny, allowedMimeTypesInScriptTag } from './util'; -const trimRegex = /[\u00a0]*[\d|#|\-|\*|\u2022]+\.?/; -const hexColorRegex = /^#[\d,a-f,A-F]{0,6}$/; +const trimRegex = /[\u00a0]*[\d#\-\*\u2022]+\.?/; +const hexColorRegex = /^#[\da-fA-F]{0,6}$/; const inlineElements = ['a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'object', 'q', @@ -54,7 +54,11 @@ function doWrapping(individualLines: boolean, args: any) { return; } } - const syntax = 'html'; + args = args || {}; + if (!args['language']) { + args['language'] = editor.document.languageId; + } + const syntax = getSyntaxFromArgs(args) || 'html'; const rootNode = parseDocument(editor.document, false); let inPreview = false; @@ -80,8 +84,8 @@ function doWrapping(individualLines: boolean, args: any) { const firstLineOfSelection = editor.document.lineAt(rangeToReplace.start).text.substr(rangeToReplace.start.character); const matches = firstLineOfSelection.match(/^(\s*)/); - const extraWhiteSpaceSelected = matches ? matches[1].length : 0; - rangeToReplace = new vscode.Range(rangeToReplace.start.line, rangeToReplace.start.character + extraWhiteSpaceSelected, rangeToReplace.end.line, rangeToReplace.end.character); + const extraWhitespaceSelected = matches ? matches[1].length : 0; + rangeToReplace = new vscode.Range(rangeToReplace.start.line, rangeToReplace.start.character + extraWhitespaceSelected, rangeToReplace.end.line, rangeToReplace.end.character); let textToWrapInPreview: string[]; let textToReplace = editor.document.getText(rangeToReplace); @@ -90,8 +94,8 @@ function doWrapping(individualLines: boolean, args: any) { } else { const wholeFirstLine = editor.document.lineAt(rangeToReplace.start).text; const otherMatches = wholeFirstLine.match(/^(\s*)/); - const preceedingWhiteSpace = otherMatches ? otherMatches[1] : ''; - textToWrapInPreview = rangeToReplace.isSingleLine ? [textToReplace] : ['\n\t' + textToReplace.split('\n' + preceedingWhiteSpace).join('\n\t') + '\n']; + const preceedingWhitespace = otherMatches ? otherMatches[1] : ''; + textToWrapInPreview = rangeToReplace.isSingleLine ? [textToReplace] : ['\n\t' + textToReplace.split('\n' + preceedingWhitespace).join('\n\t') + '\n']; } textToWrapInPreview = textToWrapInPreview.map(e => e.replace(/(\$\d)/g, '\\$1')); @@ -487,7 +491,7 @@ export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocumen } let valid = true; - let foundSpace = false; // If < is found before finding whitespace, then its valid abbreviation. Eg: | undefined { const completionResult = this.provideCompletionItemsInternal(document, position, context); if (!completionResult) { @@ -76,20 +79,55 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi } if (validateLocation) { - rootNode = parseDocument(document, false); - currentNode = getNode(rootNode, position, true); - if (isStyleAttribute(currentNode, position)) { + const lsDoc = TextDocument.create(document.uri.toString(), 'html', 0, document.getText()); + const parsedLsDoc = this.htmlLS.parseHTMLDocument(lsDoc); + const positionOffset = document.offsetAt(position); + const node = parsedLsDoc.findNodeAt(positionOffset); + + if (node.tag === 'script') { + if (node.attributes && 'type' in node.attributes) { + const rawTypeAttrValue = node.attributes['type']; + if (rawTypeAttrValue) { + const typeAttrValue = trimQuotes(rawTypeAttrValue); + if (typeAttrValue === 'application/javascript' || typeAttrValue === 'text/javascript') { + if (!getSyntaxFromArgs({ language: 'javascript' })) { + return; + } else { + validateLocation = false; + } + } + + else if (allowedMimeTypesInScriptTag.indexOf(trimQuotes(rawTypeAttrValue)) > -1) { + validateLocation = false; + } + } + } else { + return; + } + } + else if (node.tag === 'style') { syntax = 'css'; validateLocation = false; } else { - const embeddedCssNode = getEmbeddedCssNodeIfAny(document, currentNode, position); - if (embeddedCssNode) { - currentNode = getNode(embeddedCssNode, position, true); - syntax = 'css'; + if (node.attributes && node.attributes['style']) { + const scanner = this.htmlLS.createScanner(document.getText(), node.start); + let tokenType = scanner.scan(); + let prevAttr = undefined; + while (tokenType !== TokenType.EOS && (scanner.getTokenEnd() <= positionOffset)) { + tokenType = scanner.scan(); + if (tokenType === TokenType.AttributeName) { + prevAttr = scanner.getTokenText(); + } + } + if (prevAttr === 'style') { + syntax = 'css'; + validateLocation = false; + } } } } + } const extractAbbreviationResults = helper.extractAbbreviation(document, position, !isStyleSheet(syntax)); @@ -158,4 +196,4 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi return new vscode.CompletionList(newItems, true); }); } -} \ No newline at end of file +} diff --git a/extensions/emmet/src/test/abbreviationAction.test.ts b/extensions/emmet/src/test/abbreviationAction.test.ts index 0a99bae1862..31f46891965 100644 --- a/extensions/emmet/src/test/abbreviationAction.test.ts +++ b/extensions/emmet/src/test/abbreviationAction.test.ts @@ -264,16 +264,6 @@ suite('Tests for Expand Abbreviations (HTML)', () => { }); }); - test('No expanding text in completion list inside style tag if position is not for property name (HTML)', () => { - return withRandomFileEditor(htmlContents, 'html', (editor, _doc) => { - editor.selection = new Selection(13, 14, 13, 14); - const cancelSrc = new CancellationTokenSource(); - const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke }); - assert.equal(!completionPromise, true, `Got unexpected comapletion promise instead of undefined`); - return Promise.resolve(); - }); - }); - test('Expand css when inside style attribute (HTML)', () => { const styleAttributeContent = '
'; return withRandomFileEditor(styleAttributeContent, 'html', async (editor, _doc) => { diff --git a/extensions/emmet/src/test/wrapWithAbbreviation.test.ts b/extensions/emmet/src/test/wrapWithAbbreviation.test.ts index 9fc924508e2..d5a4a2bce3c 100644 --- a/extensions/emmet/src/test/wrapWithAbbreviation.test.ts +++ b/extensions/emmet/src/test/wrapWithAbbreviation.test.ts @@ -134,19 +134,7 @@ suite('Tests for Wrap with Abbreviations', () => { `; - - return withRandomFileEditor(contents, 'html', (editor, _) => { - editor.selections = [new Selection(2, 0, 2, 0)]; - const promise = wrapWithAbbreviation({ abbreviation: 'li.hello|c' }); - if (!promise) { - assert.equal(1, 2, 'Wrap returned undefined instead of promise.'); - return Promise.resolve(); - } - return promise.then(() => { - assert.equal(editor.document.getText(), expectedContents); - return Promise.resolve(); - }); - }); + return testWrapWithAbbreviation([new Selection(2, 0, 2, 0)], 'li.hello|c', expectedContents, contents); }); test('Wrap with abbreviation entire node when cursor is on opening tag', () => { @@ -162,19 +150,7 @@ suite('Tests for Wrap with Abbreviations', () => { `; - - return withRandomFileEditor(contents, 'html', (editor, _) => { - editor.selections = [new Selection(1, 1, 1, 1)]; - const promise = wrapWithAbbreviation({ abbreviation: 'div' }); - if (!promise) { - assert.equal(1, 2, 'Wrap returned undefined instead of promise.'); - return Promise.resolve(); - } - return promise.then(() => { - assert.equal(editor.document.getText(), expectedContents); - return Promise.resolve(); - }); - }); + return testWrapWithAbbreviation([new Selection(1, 1, 1, 1)], 'div', expectedContents, contents); }); test('Wrap with abbreviation entire node when cursor is on closing tag', () => { @@ -190,19 +166,7 @@ suite('Tests for Wrap with Abbreviations', () => { `; - - return withRandomFileEditor(contents, 'html', (editor, _) => { - editor.selections = [new Selection(3, 1, 3, 1)]; - const promise = wrapWithAbbreviation({ abbreviation: 'div' }); - if (!promise) { - assert.equal(1, 2, 'Wrap returned undefined instead of promise.'); - return Promise.resolve(); - } - return promise.then(() => { - assert.equal(editor.document.getText(), expectedContents); - return Promise.resolve(); - }); - }); + return testWrapWithAbbreviation([new Selection(3, 1, 3, 1)], 'div', expectedContents, contents); }); test('Wrap with multiline abbreviation doesnt add extra spaces', () => { @@ -215,19 +179,7 @@ suite('Tests for Wrap with Abbreviations', () => {
  • hello
  • `; - - return withRandomFileEditor(contents, 'html', (editor, _) => { - editor.selections = [new Selection(1, 2, 1, 2)]; - const promise = wrapWithAbbreviation({ abbreviation: 'ul>li>a' }); - if (!promise) { - assert.equal(1, 2, 'Wrap returned undefined instead of promise.'); - return Promise.resolve(); - } - return promise.then(() => { - assert.equal(editor.document.getText(), expectedContents); - return Promise.resolve(); - }); - }); + return testWrapWithAbbreviation([new Selection(1, 2, 1, 2)], 'ul>li>a', expectedContents, contents); }); test('Wrap individual lines with abbreviation', () => { @@ -245,18 +197,7 @@ suite('Tests for Wrap with Abbreviations', () => { `; - return withRandomFileEditor(contents, 'html', (editor, _) => { - editor.selections = [new Selection(2, 2, 3, 33)]; - const promise = wrapIndividualLinesWithAbbreviation({ abbreviation: 'ul>li.hello$*' }); - if (!promise) { - assert.equal(1, 2, 'Wrap Individual Lines with Abbreviation returned undefined.'); - return Promise.resolve(); - } - return promise.then(() => { - assert.equal(editor.document.getText(), wrapIndividualLinesExpected); - return Promise.resolve(); - }); - }); + return testWrapIndividualLinesWithAbbreviation([new Selection(2, 2, 3, 33)], 'ul>li.hello$*', wrapIndividualLinesExpected, contents); }); test('Wrap individual lines with abbreviation with extra space selected', () => { @@ -274,18 +215,7 @@ suite('Tests for Wrap with Abbreviations', () => { `; - return withRandomFileEditor(contents, 'html', (editor, _) => { - editor.selections = [new Selection(2, 1, 4, 0)]; - const promise = wrapIndividualLinesWithAbbreviation({ abbreviation: 'ul>li.hello$*' }); - if (!promise) { - assert.equal(1, 2, 'Wrap Individual Lines with Abbreviation returned undefined.'); - return Promise.resolve(); - } - return promise.then(() => { - assert.equal(editor.document.getText(), wrapIndividualLinesExpected); - return Promise.resolve(); - }); - }); + return testWrapIndividualLinesWithAbbreviation([new Selection(2, 1, 4, 0)], 'ul>li.hello$*', wrapIndividualLinesExpected, contents); }); test('Wrap individual lines with abbreviation with comment filter', () => { @@ -305,18 +235,7 @@ suite('Tests for Wrap with Abbreviations', () => { `; - return withRandomFileEditor(contents, 'html', (editor, _) => { - editor.selections = [new Selection(2, 2, 3, 33)]; - const promise = wrapIndividualLinesWithAbbreviation({ abbreviation: 'ul>li.hello*|c' }); - if (!promise) { - assert.equal(1, 2, 'Wrap Individual Lines with Abbreviation returned undefined.'); - return Promise.resolve(); - } - return promise.then(() => { - assert.equal(editor.document.getText(), wrapIndividualLinesExpected); - return Promise.resolve(); - }); - }); + return testWrapIndividualLinesWithAbbreviation([new Selection(2, 2, 3, 33)], 'ul>li.hello*|c', wrapIndividualLinesExpected, contents); }); test('Wrap individual lines with abbreviation and trim', () => { @@ -334,19 +253,7 @@ suite('Tests for Wrap with Abbreviations', () => { `; - return withRandomFileEditor(contents, 'html', (editor, _) => { - editor.selections = [new Selection(2, 3, 3, 16)]; - const promise = wrapIndividualLinesWithAbbreviation({ abbreviation: 'ul>li.hello$*|t' }); - if (!promise) { - assert.equal(1, 2, 'Wrap Individual Lines with Abbreviation returned undefined.'); - return Promise.resolve(); - } - - return promise.then(() => { - assert.equal(editor.document.getText(), wrapIndividualLinesExpected); - return Promise.resolve(); - }); - }); + return testWrapIndividualLinesWithAbbreviation([new Selection(2, 3, 3, 16)], 'ul>li.hello$*|t', wrapIndividualLinesExpected, contents); }); test('Wrap with abbreviation and format set to false', () => { @@ -384,11 +291,35 @@ suite('Tests for Wrap with Abbreviations', () => { return testWrapWithAbbreviation([new Selection(2, 4, 3, 9), new Selection(5, 4, 6, 9)], 'div', wrapMultiLineExpected, htmlContentsForWrapMultiLineTests); }); + + test('Wrap multiline with abbreviation uses className for jsx files', () => { + const wrapMultiLineJsxExpected = ` + +`; + + return testWrapWithAbbreviation([new Selection(2,2,3,33)], '.hello', wrapMultiLineJsxExpected, htmlContentsForWrapTests, 'jsx'); + }); + + test('Wrap individual line with abbreviation uses className for jsx files', () => { + const wrapIndividualLinesJsxExpected = ` + +`; + + return testWrapIndividualLinesWithAbbreviation([new Selection(2,2,3,33)], '.hello$*', wrapIndividualLinesJsxExpected, htmlContentsForWrapTests, 'jsx'); + }); }); -function testWrapWithAbbreviation(selections: Selection[], abbreviation: string, expectedContents: string, input: string = htmlContentsForWrapTests): Thenable { - return withRandomFileEditor(input, 'html', (editor, _) => { +function testWrapWithAbbreviation(selections: Selection[], abbreviation: string, expectedContents: string, input: string = htmlContentsForWrapTests, fileExtension: string = 'html'): Thenable { + return withRandomFileEditor(input, fileExtension, (editor, _) => { editor.selections = selections; const promise = wrapWithAbbreviation({ abbreviation }); if (!promise) { @@ -402,3 +333,19 @@ function testWrapWithAbbreviation(selections: Selection[], abbreviation: string, }); }); } + +function testWrapIndividualLinesWithAbbreviation(selections: Selection[], abbreviation: string, expectedContents: string, input: string = htmlContentsForWrapTests, fileExtension: string = 'html'): Thenable { + return withRandomFileEditor(input, fileExtension, (editor, _) => { + editor.selections = selections; + const promise = wrapIndividualLinesWithAbbreviation({ abbreviation }); + if (!promise) { + assert.equal(1, 2, 'Wrap individual lines with Abbreviation returned undefined.'); + return Promise.resolve(); + } + + return promise.then(() => { + assert.equal(editor.document.getText(), expectedContents); + return Promise.resolve(); + }); + }); +} diff --git a/extensions/emmet/src/util.ts b/extensions/emmet/src/util.ts index 2b6ab87c98b..b6281272851 100644 --- a/extensions/emmet/src/util.ts +++ b/extensions/emmet/src/util.ts @@ -95,11 +95,11 @@ export function getMappingForIncludedLanguages(): any { /** * Get the corresponding emmet mode for given vscode language mode -* Eg: jsx for typescriptreact/javascriptreact or pug for jade -* If the language is not supported by emmet or has been exlcuded via `exlcudeLanguages` setting, +* E.g.: jsx for typescriptreact/javascriptreact or pug for jade +* If the language is not supported by emmet or has been excluded via `excludeLanguages` setting, * then nothing is returned * -* @param exlcudedLanguages Array of language ids that user has chosen to exlcude for emmet +* @param excludedLanguages Array of language ids that user has chosen to exclude for emmet */ export function getEmmetMode(language: string, excludedLanguages: string[]): string | undefined { if (!language || excludedLanguages.indexOf(language) > -1) { @@ -608,3 +608,18 @@ export function isStyleAttribute(currentNode: Node | null, position: vscode.Posi } +export function trimQuotes(s: string) { + if (s.length <= 1) { + return s.replace(/['"]/, ''); + } + + if (s[0] === `'` || s[0] === `"`) { + s = s.slice(1); + } + + if (s[s.length - 1] === `'` || s[s.length - 1] === `"`) { + s = s.slice(0, -1); + } + + return s; +} \ No newline at end of file diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index 22f16e39770..7b22c533426 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -40,10 +40,10 @@ resolved "https://registry.yarnpkg.com/@emmetio/stream-reader/-/stream-reader-2.2.0.tgz#46cffea119a0a003312a21c2d9b5628cb5fcd442" integrity sha1-Rs/+oRmgoAMxKiHC2bVijLX81EI= -"@types/node@8.0.33": - version "8.0.33" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd" - integrity sha512-vmCdO8Bm1ExT+FWfC9sd9r4jwqM7o97gGy2WBshkkXbf/2nLAJQUrZfIhw27yVOtLUev6kSZc4cav/46KbDd8A== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== ajv@^5.1.0: version "5.3.0" @@ -2469,20 +2469,44 @@ vinyl@~2.0.1: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" -vscode-emmet-helper@^1.2.12: - version "1.2.12" - resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-1.2.12.tgz#6a75d5a74af735db179c708a9a91feb191f3edb5" - integrity sha512-pCo+BNgP3lGuzTIGP1IMOGILpNGVopiAu02FrDC4ctEQQ5vFIaMtI4HxDGAw2Zu7pqGEHn6Z1KFmOb2Hd/xkHA== +vscode-emmet-helper@^1.2.15: + version "1.2.15" + resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-1.2.15.tgz#62dbfbf49bb9ebe329cb7bffdda5aaac725eea7a" + integrity sha512-JplvmMMWSvm/6/dZezix2ADPM49u6YahPYjs/QToohUpomW/2Eb27ecCrkCyOGBPfKLKGiOPHCssss8TSDA9ag== dependencies: "@emmetio/extract-abbreviation" "0.1.6" jsonc-parser "^1.0.0" vscode-languageserver-types "^3.6.0-next.1" +vscode-html-languageservice@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.3.tgz#0aeae18a59000e317447ea34965f72680a2140ef" + integrity sha512-U+upM3gHp3HaF3wXAnUduA6IDKcz6frWS/dTAju3cZVIyZwOLBBFElQVlLH0ycHyMzqUFrjvdv+kEyPAEWfQ/g== + dependencies: + vscode-languageserver-types "^3.15.0-next.2" + vscode-nls "^4.1.1" + vscode-uri "^2.0.3" + +vscode-languageserver-types@^3.15.0-next.2: + version "3.15.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" + integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== + vscode-languageserver-types@^3.6.0-next.1: version "3.6.0-next.1" resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.6.0-next.1.tgz#98e488d3f87b666b4ee1a3d89f0023e246d358f3" integrity sha512-n4G+hCgZwAhtcJSCkwJP153TLdcEBWwrIrb3Su/SpOkhmU7KjDgxaQBLA45hf+QbhB8uKQb+TVStPvbuYFHSMA== +vscode-nls@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" + integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== + +vscode-uri@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543" + integrity sha512-4D3DI3F4uRy09WNtDGD93H9q034OHImxiIcSq664Hq1Y1AScehlP3qqZyTkX/RWxeu0MRMHGkrxYqm2qlDF/aw== + vscode@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.0.1.tgz#3d161200615fe2af1d92ddc650751159411a513b" diff --git a/extensions/extension-editing/package.json b/extensions/extension-editing/package.json index 8ceab79d04e..9c07a2568aa 100644 --- a/extensions/extension-editing/package.json +++ b/extensions/extension-editing/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "^1.4.0" }, @@ -53,6 +54,6 @@ }, "devDependencies": { "@types/markdown-it": "0.0.2", - "@types/node": "^8.10.25" + "@types/node": "^10.14.8" } } diff --git a/extensions/extension-editing/yarn.lock b/extensions/extension-editing/yarn.lock index d82f7c212a0..971bf580ba7 100644 --- a/extensions/extension-editing/yarn.lock +++ b/extensions/extension-editing/yarn.lock @@ -7,16 +7,16 @@ resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.2.tgz#5d9ad19e6e6508cdd2f2596df86fd0aade598660" integrity sha1-XZrRnm5lCM3S8llt+G/Qqt5ZhmA= +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== + "@types/node@^6.0.46": version "6.0.78" resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.78.tgz#5d4a3f579c1524e01ee21bf474e6fba09198f470" integrity sha512-+vD6E8ixntRzzZukoF3uP1iV+ZjVN3koTcaeK+BEoc/kSfGbLDIGC7RmCaUgVpUfN6cWvfczFRERCyKM9mkvXg== -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== - argparse@^1.0.7: version "1.0.9" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" diff --git a/extensions/fsharp/cgmanifest.json b/extensions/fsharp/cgmanifest.json index df594e070bb..47351a1a0b4 100644 --- a/extensions/fsharp/cgmanifest.json +++ b/extensions/fsharp/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "ionide/ionide-fsgrammar", "repositoryUrl": "https://github.com/ionide/ionide-fsgrammar", - "commitHash": "24c1588529af144d205f66fbcec6889500f9aaa9" + "commitHash": "687070defaf355022a5d82d091258eccfea7317c" } }, "license": "MIT", @@ -15,4 +15,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/fsharp/package.json b/extensions/fsharp/package.json index 8aee9182f58..b7050e22b4e 100644 --- a/extensions/fsharp/package.json +++ b/extensions/fsharp/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js ionide/ionide-fsgrammar grammar/fsharp.json ./syntaxes/fsharp.tmLanguage.json" diff --git a/extensions/fsharp/syntaxes/fsharp.tmLanguage.json b/extensions/fsharp/syntaxes/fsharp.tmLanguage.json index 9a9b1b1f2fd..20cfc9ecde7 100644 --- a/extensions/fsharp/syntaxes/fsharp.tmLanguage.json +++ b/extensions/fsharp/syntaxes/fsharp.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/ionide/ionide-fsgrammar/commit/be0bdfd1e272b6633f5edf1429052fe9fa4df7c1", + "version": "https://github.com/ionide/ionide-fsgrammar/commit/687070defaf355022a5d82d091258eccfea7317c", "name": "fsharp", "scopeName": "source.fsharp", "patterns": [ @@ -238,7 +238,7 @@ }, { "name": "keyword.fsharp", - "match": "\\b(private|to|public|internal|function|yield!|yield|class|exception|match|delegate|of|new|in|as|if|then|else|elif|for|begin|end|inherit|do|let\\!|return\\!|return|interface|with|abstract|property|union|enum|member|try|finally|and|when|use|use\\!|struct|while|mutable)(?!')\\b" + "match": "\\b(private|to|public|internal|function|yield!|yield|class|exception|match|delegate|of|new|in|as|if|then|else|elif|for|begin|end|inherit|do|let\\!|return\\!|return|interface|with|abstract|enum|member|try|finally|and|when|or|use|use\\!|struct|while|mutable|assert|base|done|downcast|downto|extern|fixed|global|lazy|upcast|not)(?!')\\b" }, { "name": "keyword.fsharp", @@ -285,6 +285,33 @@ } ] }, + { + "begin": "(\\()", + "end": "(\\))", + "beginCaptures": { + "1": { + "name": "keyword.symbol.fsharp" + } + }, + "endCaptures": { + "1": { + "name": "keyword.symbol.fsharp" + } + }, + "patterns": [ + { + "match": "(([?[:alpha:]0-9'`^._ ]+))+", + "captures": { + "1": { + "name": "entity.name.type.fsharp" + } + } + }, + { + "include": "#tuple_signature" + } + ] + }, { "match": "(?!when|and|or\\b)\\b([\\w0-9'`^._]+)", "comments": "Here we need the \\w modifier in order to check that the words isn't blacklisted", @@ -308,6 +335,44 @@ } ] }, + "anonymous_record_declaration": { + "begin": "(\\{\\|)", + "end": "(\\|\\})", + "beginCaptures": { + "1": { + "name": "keyword.symbol.fsharp" + } + }, + "endCaptures": { + "1": { + "name": "keyword.symbol.fsharp" + } + }, + "patterns": [ + { + "match": "[[:alpha:]0-9'`^_ ]+(:)", + "captures": { + "1": { + "name": "keyword.symbol.fsharp" + } + } + }, + { + "match": "([[:alpha:]0-9'`^_ ]+)", + "captures": { + "1": { + "name": "entity.name.type.fsharp" + } + } + }, + { + "include": "#anonymous_record_declaration" + }, + { + "include": "#keywords" + } + ] + }, "record_signature": { "patterns": [ { @@ -536,7 +601,7 @@ }, { "name": "constant.others.fsharp", - "match": "\\b(true|false|null|unit)\\b" + "match": "\\b(true|false|null|unit|void)\\b" } ] }, @@ -571,7 +636,7 @@ "include": "#common_declaration" }, { - "match": "(\\?{0,1})([[:alpha:]0-9'`^._ ]+)\\s*(:)(\\s*([[:alpha:]0-9'`^._ ]+)){0,1}", + "match": "(\\?{0,1})([[:alpha:]0-9'`^._ ]+)\\s*(:)((?!with\\b)\\b([\\w0-9'`^._ ]+)){0,1}", "captures": { "1": { "name": "keyword.symbol.fsharp" @@ -761,20 +826,31 @@ ] }, { - "match": "(\\*)(\\s*([?[:alpha:]0-9'`^._ ]+))*", - "captures": { + "begin": "(\\*)(\\s*([?[:alpha:]0-9'`^._ ]+))*", + "beginCaptures": { "1": { "name": "keyword.symbol.fsharp" }, "2": { "name": "entity.name.type.fsharp" } - } + }, + "end": "(?==)|(?=\\))", + "endCaptures": { + "1": { + "name": "keyword.symbol.fsharp" + } + }, + "patterns": [ + { + "include": "#tuple_signature" + } + ] }, { - "begin": "(<(?![[:space:]]*\\)))", + "begin": "(<+(?![[:space:]]*\\)))", "beginComment": "The group (?![[:space:]]*\\) is for protection against overload operator. static member (<)", - "end": "((?)", + "end": "((?|\\))", "endComment": "The group (? when using SRTP synthax", "beginCaptures": { "1": { @@ -792,6 +868,9 @@ } ] }, + { + "include": "#anonymous_record_declaration" + }, { "begin": "({)", "end": "(})", @@ -826,7 +905,7 @@ "patterns": [ { "name": "binding.fsharp", - "begin": "\\b(let mutable|static let mutable|let inline|let|member val|static member inline|static member|default|member|override|let!)(\\s+rec|mutable)?(\\s+\\[\\<.*\\>\\])?\\s*(private|internal|public)?\\s+(\\[[^-=]*\\]|[_[:alpha:]]([_[:alpha:]0-9,\\._]+)*|``[_[:alpha:]]([_[:alpha:]0-9,\\._`\\s]+|(?<=,)\\s)*)?", + "begin": "\\b(let mutable|static let mutable|let inline|let|member val|static member inline|static member|default|member|override|let!)(\\s+rec|mutable)?(\\s+\\[\\<.*\\>\\])?\\s*(private|internal|public)?\\s+(\\[[^-=]*\\]|[_[:alpha:]]([_[:alpha:]0-9\\._]+)*|``[_[:alpha:]]([_[:alpha:]0-9\\._`\\s]+|(?<=,)\\s)*)?", "end": "\\s*(with\\b|=|\\n+=|(?<=\\=))", "beginCaptures": { "1": { @@ -856,6 +935,26 @@ } ] }, + { + "name": "binding.fsharp", + "begin": "\\b((get|set)\\s*(?=\\())(\\[[^-=]*\\]|[_[:alpha:]]([_[:alpha:]0-9\\._]+)*|``[_[:alpha:]]([_[:alpha:]0-9\\._`\\s]+|(?<=,)\\s)*)?", + "end": "\\s*(=|\\n+=|(?<=\\=))", + "beginCaptures": { + "3": { + "name": "variable.fsharp" + } + }, + "endCaptures": { + "1": { + "name": "keyword.fsharp" + } + }, + "patterns": [ + { + "include": "#common_binding_definition" + } + ] + }, { "name": "binding.fsharp", "begin": "\\b(static val mutable|val mutable|val)(\\s+rec|mutable)?(\\s+\\[\\<.*\\>\\])?\\s*(private|internal|public)?\\s+(\\[[^-=]*\\]|[_[:alpha:]]([_[:alpha:]0-9,\\._]+)*|``[_[:alpha:]]([_[:alpha:]0-9,\\._`\\s]+|(?<=,)\\s)*)?", @@ -882,6 +981,29 @@ "include": "#common_binding_definition" } ] + }, + { + "name": "binding.fsharp", + "begin": "\\b(new)\\b\\s+(\\()", + "end": "(\\))", + "beginCaptures": { + "1": { + "name": "keyword.fsharp" + }, + "2": { + "name": "keyword.fsharp" + } + }, + "endCaptures": { + "1": { + "name": "keyword.fsharp" + } + }, + "patterns": [ + { + "include": "#common_binding_definition" + } + ] } ] }, @@ -920,13 +1042,16 @@ } }, { - "match": "([[:alpha:]0-9'`^._]+)|``([[:alpha:]0-9'^._ ]+)``", + "match": "(``([[:alpha:]0-9'^._ ]+)``|[[:alpha:]0-9'`^._]+)", "captures": { "1": { "name": "entity.name.type.fsharp" } } }, + { + "include": "#anonymous_record_declaration" + }, { "include": "#keywords" } @@ -938,7 +1063,7 @@ "patterns": [ { "name": "keyword.fsharp", - "match": "\\b(private|to|public|internal|function|yield!|yield|class|exception|match|delegate|of|new|in|as|if|then|else|elif|for|begin|end|inherit|do|let\\!|return\\!|return|interface|with|abstract|property|union|enum|member|try|finally|and|when|or|use|use\\!|struct|while|mutable)(?!')\\b" + "match": "\\b(private|to|public|internal|function|yield!|yield|class|exception|match|delegate|of|new|in|as|if|then|else|elif|for|begin|end|inherit|do|let\\!|return\\!|return|interface|with|abstract|enum|member|try|finally|and|when|or|use|use\\!|struct|while|mutable|assert|base|done|downcast|downto|extern|fixed|global|lazy|upcast|not)(?!')\\b" }, { "name": "keyword.symbol.fsharp", @@ -950,7 +1075,7 @@ "patterns": [ { "name": "entity.name.section.fsharp", - "begin": "\\b(namespace|module)\\s*(public|internal|private)?\\s+([[:alpha:]][[:alpha:]0-9'_. ]*)", + "begin": "\\b(namespace global)|(namespace|module)\\s*(public|internal|private|rec)?\\s+([[:alpha:]][[:alpha:]0-9'_. ]*)", "end": "(\\s?=|\\s|$)", "beginCaptures": { "1": { @@ -960,6 +1085,9 @@ "name": "keyword.fsharp" }, "3": { + "name": "keyword.fsharp" + }, + "4": { "name": "entity.name.section.fsharp" } }, @@ -1007,6 +1135,9 @@ "name": "entity.name.section.fsharp" } } + }, + { + "include": "#comments" } ] }, @@ -1142,7 +1273,7 @@ "match": "\\(\\)" }, { - "match": "(\\?{0,1})(``[[:alpha:]0-9'`^:,._ ]+``|[[:alpha:]0-9'`<>^._ ]\\w*)", + "match": "(\\?{0,1})(``[[:alpha:]0-9'`^:,._ ]+``|(?!private\\b)\\b[\\w[:alpha:]0-9'`<>^._ ]+)", "captures": { "1": { "name": "keyword.symbol.fsharp" @@ -1200,6 +1331,9 @@ } } }, + { + "include": "#anonymous_record_declaration" + }, { "begin": "(\\?{0,1})([[:alpha:]0-9'`^._ ]+)\\s*(:)(\\s*([?[:alpha:]0-9'`^._ ]+)(<))", "end": "(>)", diff --git a/extensions/fsharp/test/colorize-results/test_fs.json b/extensions/fsharp/test/colorize-results/test_fs.json index 37c0b61c14a..e5736fc10aa 100644 --- a/extensions/fsharp/test/colorize-results/test_fs.json +++ b/extensions/fsharp/test/colorize-results/test_fs.json @@ -604,28 +604,6 @@ "hc_black": "keyword: #569CD6" } }, - { - "c": " get", - "t": "source.fsharp", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "()", - "t": "source.fsharp constant.language.unit.fsharp", - "r": { - "dark_plus": "constant.language: #569CD6", - "light_plus": "constant.language: #0000FF", - "dark_vs": "constant.language: #569CD6", - "light_vs": "constant.language: #0000FF", - "hc_black": "constant.language: #569CD6" - } - }, { "c": " ", "t": "source.fsharp", @@ -637,9 +615,42 @@ "hc_black": "default: #FFFFFF" } }, + { + "c": "get", + "t": "source.fsharp binding.fsharp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "()", + "t": "source.fsharp binding.fsharp constant.language.unit.fsharp", + "r": { + "dark_plus": "constant.language: #569CD6", + "light_plus": "constant.language: #0000FF", + "dark_vs": "constant.language: #569CD6", + "light_vs": "constant.language: #0000FF", + "hc_black": "constant.language: #569CD6" + } + }, + { + "c": " ", + "t": "source.fsharp binding.fsharp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, { "c": "=", - "t": "source.fsharp keyword.symbol.fsharp", + "t": "source.fsharp binding.fsharp keyword.fsharp", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -681,50 +692,6 @@ "hc_black": "keyword: #569CD6" } }, - { - "c": " set", - "t": "source.fsharp", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "(", - "t": "source.fsharp keyword.symbol.fsharp", - "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", - "dark_vs": "keyword: #569CD6", - "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6" - } - }, - { - "c": "value", - "t": "source.fsharp", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ")", - "t": "source.fsharp keyword.symbol.fsharp", - "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", - "dark_vs": "keyword: #569CD6", - "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6" - } - }, { "c": " ", "t": "source.fsharp", @@ -736,9 +703,64 @@ "hc_black": "default: #FFFFFF" } }, + { + "c": "set", + "t": "source.fsharp binding.fsharp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "(", + "t": "source.fsharp binding.fsharp keyword.symbol.fsharp", + "r": { + "dark_plus": "keyword: #569CD6", + "light_plus": "keyword: #0000FF", + "dark_vs": "keyword: #569CD6", + "light_vs": "keyword: #0000FF", + "hc_black": "keyword: #569CD6" + } + }, + { + "c": "value", + "t": "source.fsharp binding.fsharp variable.parameter.fsharp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ")", + "t": "source.fsharp binding.fsharp keyword.symbol.fsharp", + "r": { + "dark_plus": "keyword: #569CD6", + "light_plus": "keyword: #0000FF", + "dark_vs": "keyword: #569CD6", + "light_vs": "keyword: #0000FF", + "hc_black": "keyword: #569CD6" + } + }, + { + "c": " ", + "t": "source.fsharp binding.fsharp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, { "c": "=", - "t": "source.fsharp keyword.symbol.fsharp", + "t": "source.fsharp binding.fsharp keyword.fsharp", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -979,7 +1001,7 @@ } }, { - "c": " targetAge", + "c": " targetAge ", "t": "source.fsharp binding.fsharp variable.parameter.fsharp", "r": { "dark_plus": "variable: #9CDCFE", @@ -989,17 +1011,6 @@ "hc_black": "variable: #9CDCFE" } }, - { - "c": " ", - "t": "source.fsharp binding.fsharp", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, { "c": "=", "t": "source.fsharp binding.fsharp keyword.fsharp", diff --git a/extensions/git-ui/.vscodeignore b/extensions/git-ui/.vscodeignore new file mode 100644 index 00000000000..7462f7448d3 --- /dev/null +++ b/extensions/git-ui/.vscodeignore @@ -0,0 +1,8 @@ +src/** +test/** +out/** +tsconfig.json +build/** +extension.webpack.config.js +cgmanifest.json +yarn.lock diff --git a/extensions/git-ui/README.md b/extensions/git-ui/README.md new file mode 100644 index 00000000000..d418425acfe --- /dev/null +++ b/extensions/git-ui/README.md @@ -0,0 +1,7 @@ +# Git UI integration for Visual Studio Code + +**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled. + +## Features + +See [Git support in VS Code](https://code.visualstudio.com/docs/editor/versioncontrol#_git-support) to learn about the features of this extension. diff --git a/extensions/git-ui/cgmanifest.json b/extensions/git-ui/cgmanifest.json new file mode 100644 index 00000000000..f3071eb691a --- /dev/null +++ b/extensions/git-ui/cgmanifest.json @@ -0,0 +1,4 @@ +{ + "registrations": [], + "version": 1 +} \ No newline at end of file diff --git a/extensions/git-ui/extension.webpack.config.js b/extensions/git-ui/extension.webpack.config.js new file mode 100644 index 00000000000..19c0ea3042d --- /dev/null +++ b/extensions/git-ui/extension.webpack.config.js @@ -0,0 +1,17 @@ +/*--------------------------------------------------------------------------------------------- + * 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 withDefaults = require('../shared.webpack.config'); + +module.exports = withDefaults({ + context: __dirname, + entry: { + main: './src/main.ts' + } +}); diff --git a/extensions/git-ui/package.json b/extensions/git-ui/package.json new file mode 100644 index 00000000000..2f1ab43f892 --- /dev/null +++ b/extensions/git-ui/package.json @@ -0,0 +1,28 @@ +{ + "name": "git-ui", + "displayName": "%displayName%", + "description": "%description%", + "publisher": "vscode", + "version": "1.0.0", + "engines": { + "vscode": "^1.5.0" + }, + "extensionKind": "ui", + "aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217", + "enableProposedApi": true, + "categories": [ + "Other" + ], + "activationEvents": [ + "onCommand:git.credential" + ], + "main": "./out/main", + "icon": "resources/icons/git.png", + "scripts": { + "compile": "gulp compile-extension:git-ui", + "watch": "gulp watch-extension:git-ui" + }, + "devDependencies": { + "@types/node": "^10.14.8" + } +} \ No newline at end of file diff --git a/extensions/git-ui/package.nls.json b/extensions/git-ui/package.nls.json new file mode 100644 index 00000000000..5303e91f4cd --- /dev/null +++ b/extensions/git-ui/package.nls.json @@ -0,0 +1,4 @@ +{ + "displayName": "Git UI", + "description": "Git SCM UI Integration" +} \ No newline at end of file diff --git a/extensions/git-ui/resources/icons/git.png b/extensions/git-ui/resources/icons/git.png new file mode 100644 index 00000000000..51f4ae5404f Binary files /dev/null and b/extensions/git-ui/resources/icons/git.png differ diff --git a/extensions/git-ui/src/main.ts b/extensions/git-ui/src/main.ts new file mode 100644 index 00000000000..d233b753be2 --- /dev/null +++ b/extensions/git-ui/src/main.ts @@ -0,0 +1,57 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ExtensionContext, commands } from 'vscode'; + +import * as cp from 'child_process'; + +export async function deactivate(): Promise { +} + +export async function activate(context: ExtensionContext): Promise { + context.subscriptions.push(commands.registerCommand('git.credential', async (data: any) => { + try { + const { stdout, stderr } = await exec(`git credential ${data.command}`, { + stdin: data.stdin, + env: Object.assign(process.env, { GIT_TERMINAL_PROMPT: '0' }) + }); + return { stdout, stderr, code: 0 }; + } catch ({ stdout, stderr, error }) { + const code = error.code || 0; + if (stderr.indexOf('terminal prompts disabled') !== -1) { + stderr = ''; + } + return { stdout, stderr, code }; + } + })); +} + +export interface ExecResult { + error: Error | null; + stdout: string; + stderr: string; +} + + +export function exec(command: string, options: cp.ExecOptions & { stdin?: string } = {}) { + return new Promise((resolve, reject) => { + const child = cp.exec(command, options, (error, stdout, stderr) => { + (error ? reject : resolve)({ error, stdout, stderr }); + }); + if (options.stdin) { + child.stdin.write(options.stdin, (err: any) => { + if (err) { + reject(err); + return; + } + child.stdin.end((err: any) => { + if (err) { + reject(err); + } + }); + }); + } + }); +} diff --git a/src/vs/workbench/parts/terminal/browser/terminalFindWidget.css b/extensions/git-ui/src/typings/refs.d.ts similarity index 69% rename from src/vs/workbench/parts/terminal/browser/terminalFindWidget.css rename to extensions/git-ui/src/typings/refs.d.ts index 93422f893ea..a933431220b 100644 --- a/src/vs/workbench/parts/terminal/browser/terminalFindWidget.css +++ b/extensions/git-ui/src/typings/refs.d.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.monaco-workbench .simple-find-part .monaco-inputbox > .wrapper > .input { - width: 100% !important; - padding-right: 66px; -} \ No newline at end of file +/// +/// +/// \ No newline at end of file diff --git a/extensions/git-ui/tsconfig.json b/extensions/git-ui/tsconfig.json new file mode 100644 index 00000000000..27e9268b39b --- /dev/null +++ b/extensions/git-ui/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../shared.tsconfig.json", + "compilerOptions": { + "outDir": "./out", + "experimentalDecorators": true, + "typeRoots": [ + "./node_modules/@types" + ] + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file diff --git a/extensions/git-ui/yarn.lock b/extensions/git-ui/yarn.lock new file mode 100644 index 00000000000..b23b0ac0392 --- /dev/null +++ b/extensions/git-ui/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== diff --git a/extensions/git/cgmanifest.json b/extensions/git/cgmanifest.json index a7e0b63aac3..e8081d6472e 100644 --- a/extensions/git/cgmanifest.json +++ b/extensions/git/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "textmate/git.tmbundle", "repositoryUrl": "https://github.com/textmate/git.tmbundle", - "commitHash": "93897a78c6e52bef13dadc0d4091d203c5facb40" + "commitHash": "5870cf3f8abad3a6637bdf69250b5d2ded427dc4" } }, "licenseDetail": [ @@ -63,4 +63,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/git/package.json b/extensions/git/package.json index 805783706c1..90064509397 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -3,6 +3,7 @@ "displayName": "%displayName%", "description": "%description%", "publisher": "vscode", + "license": "MIT", "version": "1.0.0", "engines": { "vscode": "^1.5.0" @@ -20,7 +21,8 @@ "scripts": { "compile": "gulp compile-extension:git", "watch": "gulp watch-extension:git", - "update-grammar": "node ./build/update-grammars.js" + "update-grammar": "node ./build/update-grammars.js", + "test": "mocha" }, "contributes": { "commands": [ @@ -80,8 +82,8 @@ "title": "%command.openFile%", "category": "Git", "icon": { - "light": "resources/icons/light/open-file-mono.svg", - "dark": "resources/icons/dark/open-file-mono.svg" + "light": "resources/icons/light/open-file.svg", + "dark": "resources/icons/dark/open-file.svg" } }, { @@ -240,6 +242,11 @@ "title": "%command.branch%", "category": "Git" }, + { + "command": "git.branchFrom", + "title": "%command.branchFrom%", + "category": "Git" + }, { "command": "git.deleteBranch", "title": "%command.deleteBranch%", @@ -312,12 +319,22 @@ }, { "command": "git.pushWithTags", - "title": "%command.pushWithTags%", + "title": "%command.pushFollowTags%", "category": "Git" }, { "command": "git.pushWithTagsForce", - "title": "%command.pushWithTagsForce%", + "title": "%command.pushFollowTagsForce%", + "category": "Git" + }, + { + "command": "git.addRemote", + "title": "%command.addRemote%", + "category": "Git" + }, + { + "command": "git.removeRemote", + "title": "%command.removeRemote%", "category": "Git" }, { @@ -502,6 +519,10 @@ "command": "git.branch", "when": "config.git.enabled && gitOpenRepositoryCount != 0" }, + { + "command": "git.branchFrom", + "when": "config.git.enabled && gitOpenRepositoryCount != 0" + }, { "command": "git.deleteBranch", "when": "config.git.enabled && gitOpenRepositoryCount != 0" @@ -570,6 +591,14 @@ "command": "git.pushWithTagsForce", "when": "config.git.enabled && config.git.allowForcePush && gitOpenRepositoryCount != 0" }, + { + "command": "git.addRemote", + "when": "config.git.enabled && gitOpenRepositoryCount != 0" + }, + { + "command": "git.removeRemote", + "when": "config.git.enabled && gitOpenRepositoryCount != 0" + }, { "command": "git.sync", "when": "config.git.enabled && gitOpenRepositoryCount != 0" @@ -676,89 +705,94 @@ "group": "1_sync", "when": "scmProvider == git && config.git.allowForcePush" }, + { + "command": "git.checkout", + "group": "2_branch", + "when": "scmProvider == git" + }, { "command": "git.publish", - "group": "2_publish", + "group": "2_branch", "when": "scmProvider == git" }, { "command": "git.commitStaged", - "group": "3_commit", + "group": "4_commit", "when": "scmProvider == git" }, { "command": "git.commitStagedSigned", - "group": "3_commit", + "group": "4_commit", "when": "scmProvider == git" }, { "command": "git.commitStagedAmend", - "group": "3_commit", + "group": "4_commit", "when": "scmProvider == git" }, { "command": "git.commitAll", - "group": "3_commit", + "group": "4_commit", "when": "scmProvider == git" }, { "command": "git.commitAllSigned", - "group": "3_commit", + "group": "4_commit", "when": "scmProvider == git" }, { "command": "git.commitAllAmend", - "group": "3_commit", + "group": "4_commit", "when": "scmProvider == git" }, { "command": "git.undoCommit", - "group": "3_commit", + "group": "4_commit", "when": "scmProvider == git" }, { "command": "git.stageAll", - "group": "4_stage", + "group": "5_stage", "when": "scmProvider == git" }, { "command": "git.unstageAll", - "group": "4_stage", + "group": "5_stage", "when": "scmProvider == git" }, { "command": "git.cleanAll", - "group": "4_stage", + "group": "5_stage", "when": "scmProvider == git && !gitFreshRepository" }, { "command": "git.stashIncludeUntracked", - "group": "5_stash", + "group": "6_stash", "when": "scmProvider == git" }, { "command": "git.stash", - "group": "5_stash", + "group": "6_stash", "when": "scmProvider == git" }, { "command": "git.stashPop", - "group": "5_stash", + "group": "6_stash", "when": "scmProvider == git" }, { "command": "git.stashPopLatest", - "group": "5_stash", + "group": "6_stash", "when": "scmProvider == git" }, { "command": "git.stashApply", - "group": "5_stash", + "group": "6_stash", "when": "scmProvider == git" }, { "command": "git.stashApplyLatest", - "group": "5_stash", + "group": "6_stash", "when": "scmProvider == git" }, { @@ -999,7 +1033,7 @@ ], "markdownDescription": "%config.path%", "default": null, - "scope": "application" + "scope": "machine" }, "git.autoRepositoryDetection": { "type": [ @@ -1028,6 +1062,7 @@ }, "git.autofetch": { "type": "boolean", + "scope": "resource", "description": "%config.autofetch%", "default": false, "tags": [ @@ -1113,6 +1148,12 @@ "description": "%config.enableSmartCommit%", "default": false }, + "git.suggestSmartCommit": { + "type": "boolean", + "scope": "resource", + "description": "%config.suggestSmartCommit%", + "default": true + }, "git.enableCommitSigning": { "type": "boolean", "scope": "resource", @@ -1149,6 +1190,7 @@ "%config.postCommitCommand.sync%" ], "markdownDescription": "%config.postCommitCommand%", + "scope": "resource", "default": "none" }, "git.showInlineOpenFileAction": { @@ -1181,7 +1223,7 @@ "number", "null" ], - "default": null, + "default": 50, "description": "%config.inputValidationSubjectLength%" }, "git.detectSubmodules": { @@ -1210,12 +1252,18 @@ }, "git.ignoredRepositories": { "type": "array", + "items": { + "type": "string" + }, "default": [], "scope": "window", "description": "%config.ignoredRepositories%" }, "git.scanRepositories": { "type": "array", + "items": { + "type": "string" + }, "default": [], "scope": "resource", "description": "%config.scanRepositories%" @@ -1238,6 +1286,12 @@ "default": false, "description": "%config.fetchOnPull%" }, + "git.pullTags": { + "type": "boolean", + "scope": "resource", + "default": true, + "description": "%config.pullTags%" + }, "git.autoStash": { "type": "boolean", "scope": "resource", @@ -1264,6 +1318,12 @@ "scope": "resource", "default": true, "description": "%config.openDiffOnClick%" + }, + "git.supportCancellation": { + "type": "boolean", + "scope": "resource", + "default": false, + "description": "%config.supportCancellation%" } } }, @@ -1416,16 +1476,17 @@ "file-type": "^7.2.0", "iconv-lite": "^0.4.24", "jschardet": "^1.6.0", - "vscode-extension-telemetry": "0.1.0", + "vscode-extension-telemetry": "0.1.1", "vscode-nls": "^4.0.0", + "vscode-uri": "^2.0.0", "which": "^1.3.0" }, "devDependencies": { "@types/byline": "4.2.31", "@types/file-type": "^5.2.1", "@types/mocha": "2.2.43", - "@types/node": "^8.10.25", + "@types/node": "^10.14.8", "@types/which": "^1.0.28", "mocha": "^3.2.0" } -} \ No newline at end of file +} diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 4f749189fc7..4d8bccf4e0b 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -32,6 +32,7 @@ "command.undoCommit": "Undo Last Commit", "command.checkout": "Checkout to...", "command.branch": "Create Branch...", + "command.branchFrom": "Create Branch From...", "command.deleteBranch": "Delete Branch...", "command.renameBranch": "Rename Branch...", "command.merge": "Merge Branch...", @@ -46,8 +47,10 @@ "command.pushForce": "Push (Force)", "command.pushTo": "Push to...", "command.pushToForce": "Push to... (Force)", - "command.pushWithTags": "Push With Tags", - "command.pushWithTagsForce": "Push With Tags (Force)", + "command.pushFollowTags": "Push (Follow Tags)", + "command.pushFollowTagsForce": "Push (Follow Tags, Force)", + "command.addRemote": "Add Remote", + "command.removeRemote": "Remove Remote", "command.sync": "Sync", "command.syncRebase": "Sync (Rebase)", "command.publish": "Publish Branch", @@ -86,6 +89,7 @@ "config.ignoreLimitWarning": "Ignores the warning when there are too many changes in a repository.", "config.defaultCloneDirectory": "The default location to clone a git repository.", "config.enableSmartCommit": "Commit all changes when there are no staged changes.", + "config.suggestSmartCommit": "Suggests to enable smart commit (commit all changes when there are no staged changes).", "config.enableCommitSigning": "Enables commit signing with GPG.", "config.discardAllScope": "Controls what changes are discarded by the `Discard all changes` command. `all` discards all changes. `tracked` discards only tracked files. `prompt` shows a prompt dialog every time the action is run.", "config.decorations.enabled": "Controls whether Git contributes colors and badges to the explorer and the open editors view.", @@ -109,11 +113,13 @@ "config.rebaseWhenSync": "Force git to use rebase when running the sync command.", "config.confirmEmptyCommits": "Always confirm the creation of empty commits.", "config.fetchOnPull": "Fetch all branches when pulling or just the current one.", + "config.pullTags": "Fetch all tags when pulling.", "config.autoStash": "Stash any changes before pulling and restore them after successful pull.", "config.allowForcePush": "Controls whether force push (with or without lease) is enabled.", "config.useForcePushWithLease": "Controls whether force pushing uses the safer force-with-lease variant.", "config.confirmForcePush": "Controls whether to ask for confirmation before force-pushing.", "config.openDiffOnClick": "Controls whether the diff editor should be opened when clicking a change. Otherwise the regular editor will be opened.", + "config.supportCancellation": "Controls whether a notification comes up when running the Sync action, which allows the user to cancel the operation.", "colors.added": "Color for added resources.", "colors.modified": "Color for modified resources.", "colors.deleted": "Color for deleted resources.", @@ -121,4 +127,4 @@ "colors.ignored": "Color for ignored resources.", "colors.conflict": "Color for resources with conflicts.", "colors.submodule": "Color for submodule resources." -} \ No newline at end of file +} diff --git a/extensions/git/resources/icons/dark/check.svg b/extensions/git/resources/icons/dark/check.svg index c225b2f597f..865cc83c347 100644 --- a/extensions/git/resources/icons/dark/check.svg +++ b/extensions/git/resources/icons/dark/check.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/dark/clean.svg b/extensions/git/resources/icons/dark/clean.svg index 3770d63d5f9..de85d6ba679 100644 --- a/extensions/git/resources/icons/dark/clean.svg +++ b/extensions/git/resources/icons/dark/clean.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/dark/git.svg b/extensions/git/resources/icons/dark/git.svg index c08b1c2e403..4d9389336b9 100644 --- a/extensions/git/resources/icons/dark/git.svg +++ b/extensions/git/resources/icons/dark/git.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/dark/open-change.svg b/extensions/git/resources/icons/dark/open-change.svg index 6f785c26a5e..41ebc85a8c8 100644 --- a/extensions/git/resources/icons/dark/open-change.svg +++ b/extensions/git/resources/icons/dark/open-change.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/dark/open-file-mono.svg b/extensions/git/resources/icons/dark/open-file-mono.svg deleted file mode 100644 index 830727e70b3..00000000000 --- a/extensions/git/resources/icons/dark/open-file-mono.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extensions/git/resources/icons/dark/open-file.svg b/extensions/git/resources/icons/dark/open-file.svg index f6302185aa4..ed302ae1398 100644 --- a/extensions/git/resources/icons/dark/open-file.svg +++ b/extensions/git/resources/icons/dark/open-file.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/dark/refresh.svg b/extensions/git/resources/icons/dark/refresh.svg index d79fdaa4e8e..e1f05aadeeb 100644 --- a/extensions/git/resources/icons/dark/refresh.svg +++ b/extensions/git/resources/icons/dark/refresh.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + + diff --git a/extensions/git/resources/icons/dark/stage.svg b/extensions/git/resources/icons/dark/stage.svg index 3475c1e1963..4d9389336b9 100644 --- a/extensions/git/resources/icons/dark/stage.svg +++ b/extensions/git/resources/icons/dark/stage.svg @@ -1 +1,3 @@ -Layer 1 \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/dark/unstage.svg b/extensions/git/resources/icons/dark/unstage.svg index 2de46fcf5b5..4c5a9c1e3a5 100644 --- a/extensions/git/resources/icons/dark/unstage.svg +++ b/extensions/git/resources/icons/dark/unstage.svg @@ -1 +1,3 @@ -Layer 1 \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/light/check.svg b/extensions/git/resources/icons/light/check.svg index 3f365c4800e..e1a546660ed 100644 --- a/extensions/git/resources/icons/light/check.svg +++ b/extensions/git/resources/icons/light/check.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/light/clean.svg b/extensions/git/resources/icons/light/clean.svg index f86ec7d627d..b70626957d0 100644 --- a/extensions/git/resources/icons/light/clean.svg +++ b/extensions/git/resources/icons/light/clean.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/light/git.svg b/extensions/git/resources/icons/light/git.svg index d1049a44d0d..01a9de7d5ab 100644 --- a/extensions/git/resources/icons/light/git.svg +++ b/extensions/git/resources/icons/light/git.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/light/open-change.svg b/extensions/git/resources/icons/light/open-change.svg index 873b93d8106..772c3c198fc 100644 --- a/extensions/git/resources/icons/light/open-change.svg +++ b/extensions/git/resources/icons/light/open-change.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/light/open-file-mono.svg b/extensions/git/resources/icons/light/open-file-mono.svg deleted file mode 100644 index fa3f245b755..00000000000 --- a/extensions/git/resources/icons/light/open-file-mono.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extensions/git/resources/icons/light/open-file.svg b/extensions/git/resources/icons/light/open-file.svg index d23a23c6b5f..392a840c5ef 100644 --- a/extensions/git/resources/icons/light/open-file.svg +++ b/extensions/git/resources/icons/light/open-file.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/light/refresh.svg b/extensions/git/resources/icons/light/refresh.svg index e0345748192..9b1d9108409 100644 --- a/extensions/git/resources/icons/light/refresh.svg +++ b/extensions/git/resources/icons/light/refresh.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + + diff --git a/extensions/git/resources/icons/light/stage.svg b/extensions/git/resources/icons/light/stage.svg index bdecdb0e45b..01a9de7d5ab 100644 --- a/extensions/git/resources/icons/light/stage.svg +++ b/extensions/git/resources/icons/light/stage.svg @@ -1 +1,3 @@ -Layer 1 \ No newline at end of file + + + diff --git a/extensions/git/resources/icons/light/unstage.svg b/extensions/git/resources/icons/light/unstage.svg index f5d128b2df8..d12a8ee3135 100644 --- a/extensions/git/resources/icons/light/unstage.svg +++ b/extensions/git/resources/icons/light/unstage.svg @@ -1 +1,3 @@ -Layer 1 \ No newline at end of file + + + diff --git a/extensions/git/src/api/api1.ts b/extensions/git/src/api/api1.ts index 9469580d97b..a4fd677db27 100644 --- a/extensions/git/src/api/api1.ts +++ b/extensions/git/src/api/api1.ts @@ -5,7 +5,7 @@ import { Model } from '../model'; import { Repository as BaseRepository, Resource } from '../repository'; -import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status } from './git'; +import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState } from './git'; import { Event, SourceControlInputBox, Uri, SourceControl } from 'vscode'; import { mapEvent } from '../util'; @@ -76,6 +76,10 @@ export class ApiRepository implements Repository { return this._repository.setConfig(key, value); } + getGlobalConfig(key: string): Promise { + return this._repository.getGlobalConfig(key); + } + getObjectDetails(treeish: string, path: string): Promise<{ mode: string; object: string; size: number; }> { return this._repository.getObjectDetails(treeish, path); } @@ -104,19 +108,27 @@ export class ApiRepository implements Repository { return this._repository.diff(cached); } - diffWithHEAD(path: string): Promise { + diffWithHEAD(): Promise; + diffWithHEAD(path: string): Promise; + diffWithHEAD(path?: string): Promise { return this._repository.diffWithHEAD(path); } - diffWith(ref: string, path: string): Promise { + diffWith(ref: string): Promise; + diffWith(ref: string, path: string): Promise; + diffWith(ref: string, path?: string): Promise { return this._repository.diffWith(ref, path); } - diffIndexWithHEAD(path: string): Promise { + diffIndexWithHEAD(): Promise; + diffIndexWithHEAD(path: string): Promise; + diffIndexWithHEAD(path?: string): Promise { return this._repository.diffIndexWithHEAD(path); } - diffIndexWith(ref: string, path: string): Promise { + diffIndexWith(ref: string): Promise; + diffIndexWith(ref: string, path: string): Promise; + diffIndexWith(ref: string, path?: string): Promise { return this._repository.diffIndexWith(ref, path); } @@ -124,7 +136,9 @@ export class ApiRepository implements Repository { return this._repository.diffBlobs(object1, object2); } - diffBetween(ref1: string, ref2: string, path: string): Promise { + diffBetween(ref1: string, ref2: string): Promise; + diffBetween(ref1: string, ref2: string, path: string): Promise; + diffBetween(ref1: string, ref2: string, path?: string): Promise { return this._repository.diffBetween(ref1, ref2, path); } @@ -168,17 +182,25 @@ export class ApiRepository implements Repository { return this._repository.removeRemote(name); } - fetch(remote?: string | undefined, ref?: string | undefined): Promise { - return this._repository.fetch(remote, ref); + fetch(remote?: string | undefined, ref?: string | undefined, depth?: number | undefined): Promise { + return this._repository.fetch(remote, ref, depth); } - pull(): Promise { - return this._repository.pull(); + pull(unshallow?: boolean): Promise { + return this._repository.pull(undefined, unshallow); } push(remoteName?: string, branchName?: string, setUpstream: boolean = false): Promise { return this._repository.pushTo(remoteName, branchName, setUpstream); } + + blame(path: string): Promise { + return this._repository.blame(path); + } + + log(options?: LogOptions): Promise { + return this._repository.log(options); + } } export class ApiGit implements Git { @@ -192,6 +214,14 @@ export class ApiImpl implements API { readonly git = new ApiGit(this._model); + get state(): APIState { + return this._model.state; + } + + get onDidChangeState(): Event { + return this._model.onDidChangeState; + } + get onDidOpenRepository(): Event { return mapEvent(this._model.onDidOpenRepository, r => new ApiRepository(r)); } diff --git a/extensions/git/src/api/git.d.ts b/extensions/git/src/api/git.d.ts index eb128be6609..21195974fc1 100644 --- a/extensions/git/src/api/git.d.ts +++ b/extensions/git/src/api/git.d.ts @@ -41,6 +41,7 @@ export interface Commit { readonly hash: string; readonly message: string; readonly parents: string[]; + readonly authorEmail?: string | undefined; } export interface Submodule { @@ -110,6 +111,14 @@ export interface RepositoryUIState { readonly onDidChange: Event; } +/** + * Log options. + */ +export interface LogOptions { + /** Max number of log entries to retrieve. If not specified, the default is 32. */ + readonly maxEntries?: number; +} + export interface Repository { readonly rootUri: Uri; @@ -120,6 +129,7 @@ export interface Repository { getConfigs(): Promise<{ key: string; value: string; }[]>; getConfig(key: string): Promise; setConfig(key: string, value: string): Promise; + getGlobalConfig(key: string): Promise; getObjectDetails(treeish: string, path: string): Promise<{ mode: string, object: string, size: number }>; detectObjectType(object: string): Promise<{ mimetype: string, encoding?: string }>; @@ -131,11 +141,16 @@ export interface Repository { apply(patch: string, reverse?: boolean): Promise; diff(cached?: boolean): Promise; + diffWithHEAD(): Promise; diffWithHEAD(path: string): Promise; + diffWith(ref: string): Promise; diffWith(ref: string, path: string): Promise; + diffIndexWithHEAD(): Promise; diffIndexWithHEAD(path: string): Promise; + diffIndexWith(ref: string): Promise; diffIndexWith(ref: string, path: string): Promise; diffBlobs(object1: string, object2: string): Promise; + diffBetween(ref1: string, ref2: string): Promise; diffBetween(ref1: string, ref2: string, path: string): Promise; hashObject(data: string): Promise; @@ -153,12 +168,19 @@ export interface Repository { addRemote(name: string, url: string): Promise; removeRemote(name: string): Promise; - fetch(remote?: string, ref?: string): Promise; - pull(): Promise; + fetch(remote?: string, ref?: string, depth?: number): Promise; + pull(unshallow?: boolean): Promise; push(remoteName?: string, branchName?: string, setUpstream?: boolean): Promise; + + blame(path: string): Promise; + log(options?: LogOptions): Promise; } +export type APIState = 'uninitialized' | 'initialized'; + export interface API { + readonly state: APIState; + readonly onDidChangeState: Event; readonly git: Git; readonly repositories: Repository[]; readonly onDidOpenRepository: Event; @@ -215,5 +237,6 @@ export const enum GitErrorCodes { WrongCase = 'WrongCase', CantLockRef = 'CantLockRef', CantRebaseMultipleBranches = 'CantRebaseMultipleBranches', - PatchDoesNotApply = 'PatchDoesNotApply' -} \ No newline at end of file + PatchDoesNotApply = 'PatchDoesNotApply', + NoPathFound = 'NoPathFound' +} diff --git a/extensions/git/src/askpass.ts b/extensions/git/src/askpass.ts index b0dc28f8dd6..03000c7290d 100644 --- a/extensions/git/src/askpass.ts +++ b/extensions/git/src/askpass.ts @@ -65,7 +65,7 @@ export class Askpass implements Disposable { return ipcHandlePath; } - private onRequest(req: http.ServerRequest, res: http.ServerResponse): void { + private onRequest(req: http.IncomingMessage, res: http.ServerResponse): void { const chunks: string[] = []; req.setEncoding('utf8'); req.on('data', (d: string) => chunks.push(d)); diff --git a/extensions/git/src/autofetch.ts b/extensions/git/src/autofetch.ts index f6c28946620..9fd81bfabfe 100644 --- a/extensions/git/src/autofetch.ts +++ b/extensions/git/src/autofetch.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { workspace, Disposable, EventEmitter, Memento, window, MessageItem, ConfigurationTarget } from 'vscode'; +import { workspace, Disposable, EventEmitter, Memento, window, MessageItem, ConfigurationTarget, Uri } from 'vscode'; import { Repository, Operation } from './repository'; import { eventToPromise, filterEvent, onceEvent } from './util'; import * as nls from 'vscode-nls'; @@ -60,7 +60,7 @@ export class AutoFetcher { } if (result === yes) { - const gitConfig = workspace.getConfiguration('git'); + const gitConfig = workspace.getConfiguration('git', Uri.file(this.repository.root)); gitConfig.update('autofetch', true, ConfigurationTarget.Global); } @@ -68,7 +68,7 @@ export class AutoFetcher { } private onConfiguration(): void { - const gitConfig = workspace.getConfiguration('git'); + const gitConfig = workspace.getConfiguration('git', Uri.file(this.repository.root)); if (gitConfig.get('autofetch') === false) { this.disable(); @@ -110,7 +110,7 @@ export class AutoFetcher { return; } - const period = workspace.getConfiguration('git').get('autofetchPeriod', 180) * 1000; + const period = workspace.getConfiguration('git', Uri.file(this.repository.root)).get('autofetchPeriod', 180) * 1000; const timeout = new Promise(c => setTimeout(c, period)); const whenDisabled = eventToPromise(filterEvent(this.onDidChange, enabled => !enabled)); diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index eb45f107f4b..fef9d4a1f85 100755 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -56,7 +56,13 @@ class CheckoutRemoteHeadItem extends CheckoutItem { return; } - await repository.checkoutTracking(this.ref.name); + const branches = await repository.findTrackingBranches(this.ref.name); + + if (branches.length > 0) { + await repository.checkout(branches[0].name!); + } else { + await repository.checkoutTracking(this.ref.name); + } } } @@ -93,7 +99,21 @@ class CreateBranchItem implements QuickPickItem { constructor(private cc: CommandCenter) { } - get label(): string { return localize('create branch', '$(plus) Create new branch'); } + get label(): string { return localize('create branch', '$(plus) Create new branch...'); } + get description(): string { return ''; } + + get alwaysShow(): boolean { return true; } + + async run(repository: Repository): Promise { + await this.cc.branch(repository); + } +} + +class CreateBranchFromItem implements QuickPickItem { + + constructor(private cc: CommandCenter) { } + + get label(): string { return localize('create branch from', '$(plus) Create new branch from...'); } get description(): string { return ''; } get alwaysShow(): boolean { return true; } @@ -182,7 +202,7 @@ function createCheckoutItems(repository: Repository): CheckoutItem[] { enum PushType { Push, PushTo, - PushTags, + PushFollowTags, } interface PushOptions { @@ -430,6 +450,8 @@ export class CommandCenter { return; } + url = url.trim().replace(/^git\s+clone\s+/, ''); + const config = workspace.getConfiguration('git'); let defaultCloneDirectory = config.get('defaultCloneDirectory') || os.homedir(); defaultCloneDirectory = defaultCloneDirectory.replace(/^~/, os.homedir()); @@ -467,10 +489,10 @@ export class CommandCenter { (_, token) => this.git.clone(url!, parentPath, token) ); - const choices = []; let message = localize('proposeopen', "Would you like to open the cloned repository?"); - const open = localize('openrepo', "Open Repository"); - choices.push(open); + const open = localize('openrepo', "Open"); + const openNewWindow = localize('openreponew', "Open in New Window"); + const choices = [open, openNewWindow]; const addToWorkspace = localize('add', "Add to Workspace"); if (workspace.workspaceFolders) { @@ -495,6 +517,8 @@ export class CommandCenter { commands.executeCommand('vscode.openFolder', uri); } else if (result === addToWorkspace) { workspace.updateWorkspaceFolders(workspace.workspaceFolders!.length, 0, { uri }); + } else if (result === openNewWindow) { + commands.executeCommand('vscode.openFolder', uri, true); } } catch (err) { if (/already exists and is not an empty directory/.test(err && err.stderr || '')) { @@ -579,10 +603,10 @@ export class CommandCenter { await this.git.init(repositoryPath); - const choices = []; let message = localize('proposeopen init', "Would you like to open the initialized repository?"); - const open = localize('openrepo', "Open Repository"); - choices.push(open); + const open = localize('openrepo', "Open"); + const openNewWindow = localize('openreponew', "Open in New Window"); + const choices = [open, openNewWindow]; if (!askToOpen) { return; @@ -601,6 +625,8 @@ export class CommandCenter { commands.executeCommand('vscode.openFolder', uri); } else if (result === addToWorkspace) { workspace.updateWorkspaceFolders(workspace.workspaceFolders!.length, 0, { uri }); + } else if (result === openNewWindow) { + commands.executeCommand('vscode.openFolder', uri, true); } else { await this.model.openRepository(repositoryPath); } @@ -653,10 +679,11 @@ export class CommandCenter { } if (resource) { - const resources = ([resource, ...resourceStates] as Resource[]) - .filter(r => r.type !== Status.DELETED && r.type !== Status.INDEX_DELETED); - - uris = resources.map(r => r.resourceUri); + uris = ([resource, ...resourceStates] as Resource[]) + .filter(r => r.type !== Status.DELETED && r.type !== Status.INDEX_DELETED) + .map(r => r.resourceUri); + } else if (window.activeTextEditor) { + uris = [window.activeTextEditor.document.uri]; } } @@ -665,6 +692,7 @@ export class CommandCenter { } const activeTextEditor = window.activeTextEditor; + for (const uri of uris) { const opts: TextDocumentShowOptions = { preserveFocus, @@ -711,6 +739,8 @@ export class CommandCenter { } const HEAD = await this.getLeftResource(resource); + const basename = path.basename(resource.resourceUri.fsPath); + const title = `${basename} (HEAD)`; if (!HEAD) { window.showWarningMessage(localize('HEAD not available', "HEAD version of '{0}' is not available.", path.basename(resource.resourceUri.fsPath))); @@ -721,7 +751,7 @@ export class CommandCenter { preview }; - return await commands.executeCommand('vscode.open', HEAD, opts); + return await commands.executeCommand('vscode.open', HEAD, opts, title); } @command('git.openChange') @@ -1087,7 +1117,7 @@ export class CommandCenter { if (scmResources.length === 1) { if (untrackedCount > 0) { - message = localize('confirm delete', "Are you sure you want to DELETE {0}?", path.basename(scmResources[0].resourceUri.fsPath)); + message = localize('confirm delete', "Are you sure you want to DELETE {0}?\nThis is IRREVERSIBLE!\nThis file will be FOREVER LOST.", path.basename(scmResources[0].resourceUri.fsPath)); yes = localize('delete file', "Delete file"); } else { if (scmResources[0].type === Status.DELETED) { @@ -1106,7 +1136,7 @@ export class CommandCenter { } if (untrackedCount > 0) { - message = `${message}\n\n${localize('warn untracked', "This will DELETE {0} untracked files!", untrackedCount)}`; + message = `${message}\n\n${localize('warn untracked', "This will DELETE {0} untracked files!\nThis is IRREVERSIBLE!\nThese files will be FOREVER LOST.", untrackedCount)}`; } } @@ -1147,7 +1177,7 @@ export class CommandCenter { await repository.clean(resources.map(r => r.resourceUri)); return; } else if (resources.length === 1) { - const message = localize('confirm delete', "Are you sure you want to DELETE {0}?", path.basename(resources[0].resourceUri.fsPath)); + const message = localize('confirm delete', "Are you sure you want to DELETE {0}?\nThis is IRREVERSIBLE!\nThis file will be FOREVER LOST.", path.basename(resources[0].resourceUri.fsPath)); const yes = localize('delete file', "Delete file"); const pick = await window.showWarningMessage(message, { modal: true }, yes); @@ -1228,14 +1258,23 @@ export class CommandCenter { // no changes, and the user has not configured to commit all in this case if (!noUnstagedChanges && noStagedChanges && !enableSmartCommit) { + const suggestSmartCommit = config.get('suggestSmartCommit') === true; + if (!suggestSmartCommit) { + return false; + } + // prompt the user if we want to commit all or not const message = localize('no staged changes', "There are no staged changes to commit.\n\nWould you like to automatically stage all your changes and commit them directly?"); const yes = localize('yes', "Yes"); const always = localize('always', "Always"); - const pick = await window.showWarningMessage(message, { modal: true }, yes, always); + const never = localize('never', "Never"); + const pick = await window.showWarningMessage(message, { modal: true }, yes, always, never); if (pick === always) { config.update('enableSmartCommit', true, true); + } else if (pick === never) { + config.update('suggestSmartCommit', false, true); + return false; } else if (pick !== yes) { return false; // do not commit on cancel } @@ -1419,14 +1458,16 @@ export class CommandCenter { await repository.checkout(treeish); return true; } - const createBranch = new CreateBranchItem(this); - const picks = [createBranch, ...createCheckoutItems(repository)]; + const createBranch = new CreateBranchItem(this); + const createBranchFrom = new CreateBranchFromItem(this); + const picks = [createBranch, createBranchFrom, ...createCheckoutItems(repository)]; const placeHolder = localize('select a ref to checkout', 'Select a ref to checkout'); const quickpick = window.createQuickPick(); quickpick.items = picks; quickpick.placeholder = placeHolder; + quickpick.ignoreFocusOut = true; quickpick.show(); const choice = await new Promise(c => quickpick.onDidAccept(() => c(quickpick.activeItems[0]))); @@ -1438,6 +1479,8 @@ export class CommandCenter { if (choice === createBranch) { await this._branch(repository, quickpick.value); + } else if (choice === createBranchFrom) { + await this._branch(repository, quickpick.value, true); } else { await (choice as CheckoutItem).run(repository); } @@ -1450,16 +1493,20 @@ export class CommandCenter { await this._branch(repository); } - private async _branch(repository: Repository, defaultName?: string): Promise { + @command('git.branchFrom', { repository: true }) + async branchFrom(repository: Repository): Promise { + await this._branch(repository, undefined, true); + } + + private async promptForBranchName(defaultName?: string): Promise { const config = workspace.getConfiguration('git'); const branchWhitespaceChar = config.get('branchWhitespaceChar')!; const branchValidationRegex = config.get('branchValidationRegex')!; const sanitize = (name: string) => name ? - name.trim().replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$|\[|\]$/g, branchWhitespaceChar) + name.trim().replace(/^-+/, '').replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$|\[|\]$/g, branchWhitespaceChar) : name; - const rawBranchName = await window.showInputBox({ - value: defaultName, + const rawBranchName = defaultName || await window.showInputBox({ placeHolder: localize('branch name', "Branch name"), prompt: localize('provide branch name', "Please provide a branch name"), ignoreFocusOut: true, @@ -1473,21 +1520,31 @@ export class CommandCenter { } }); - const branchName = sanitize(rawBranchName || ''); + return sanitize(rawBranchName || ''); + } + + private async _branch(repository: Repository, defaultName?: string, from = false): Promise { + const branchName = await this.promptForBranchName(defaultName); if (!branchName) { return; } - const picks = [new HEADItem(repository), ...createCheckoutItems(repository)]; - const placeHolder = localize('select a ref to create a new branch from', 'Select a ref to create a new branch from'); - const target = await window.showQuickPick(picks, { placeHolder }); + let target = 'HEAD'; - if (!target) { - return; + if (from) { + const picks = [new HEADItem(repository), ...createCheckoutItems(repository)]; + const placeHolder = localize('select a ref to create a new branch from', 'Select a ref to create the \'{0}\' branch from', branchName); + const choice = await window.showQuickPick(picks, { placeHolder }); + + if (!choice) { + return; + } + + target = choice.label; } - await repository.branch(branchName, true, target.label); + await repository.branch(branchName, true, target); } @command('git.deleteBranch', { repository: true }) @@ -1529,22 +1586,21 @@ export class CommandCenter { @command('git.renameBranch', { repository: true }) async renameBranch(repository: Repository): Promise { - const placeHolder = localize('provide branch name', "Please provide a branch name"); - const name = await window.showInputBox({ placeHolder }); + const branchName = await this.promptForBranchName(); - if (!name || name.trim().length === 0) { + if (!branchName) { return; } try { - await repository.renameBranch(name); + await repository.renameBranch(branchName); } catch (err) { switch (err.gitErrorCode) { case GitErrorCodes.InvalidBranchName: window.showErrorMessage(localize('invalid branch name', 'Invalid branch name')); return; case GitErrorCodes.BranchAlreadyExists: - window.showErrorMessage(localize('branch already exists', "A branch named '{0}' already exists", name)); + window.showErrorMessage(localize('branch already exists', "A branch named '{0}' already exists", branchName)); return; default: throw err; @@ -1722,10 +1778,8 @@ export class CommandCenter { } } - if (pushOptions.pushType === PushType.PushTags) { - await repository.pushTags(undefined, forcePushMode); - - window.showInformationMessage(localize('push with tags success', "Successfully pushed with tags.")); + if (pushOptions.pushType === PushType.PushFollowTags) { + await repository.pushFollowTags(undefined, forcePushMode); return; } @@ -1782,13 +1836,13 @@ export class CommandCenter { } @command('git.pushWithTags', { repository: true }) - async pushWithTags(repository: Repository): Promise { - await this._push(repository, { pushType: PushType.PushTags }); + async pushFollowTags(repository: Repository): Promise { + await this._push(repository, { pushType: PushType.PushFollowTags }); } @command('git.pushWithTagsForce', { repository: true }) - async pushWithTagsForce(repository: Repository): Promise { - await this._push(repository, { pushType: PushType.PushTags, forcePush: true }); + async pushFollowTagsForce(repository: Repository): Promise { + await this._push(repository, { pushType: PushType.PushFollowTags, forcePush: true }); } @command('git.pushTo', { repository: true }) @@ -1801,10 +1855,86 @@ export class CommandCenter { await this._push(repository, { pushType: PushType.PushTo, forcePush: true }); } + @command('git.addRemote', { repository: true }) + async addRemote(repository: Repository): Promise { + const remotes = repository.remotes; + + const sanitize = (name: string) => { + name = name.trim(); + return name && name.replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$|\[|\]$/g, '-'); + }; + + const resultName = await window.showInputBox({ + placeHolder: localize('remote name', "Remote name"), + prompt: localize('provide remote name', "Please provide a remote name"), + ignoreFocusOut: true, + validateInput: (name: string) => { + if (sanitize(name)) { + return null; + } + return localize('remote name format invalid', "Remote name format invalid"); + } + }); + + const name = sanitize(resultName || ''); + + if (!name) { + return; + } + + if (remotes.find(r => r.name === name)) { + window.showErrorMessage(localize('remote already exists', "Remote '{0}' already exists.", name)); + return; + } + + const url = await window.showInputBox({ + placeHolder: localize('remote url', "Remote URL"), + prompt: localize('provide remote URL', "Enter URL for remote \"{0}\"", name), + ignoreFocusOut: true + }); + + if (!url) { + return; + } + + await repository.addRemote(name, url); + } + + @command('git.removeRemote', { repository: true }) + async removeRemote(repository: Repository): Promise { + const remotes = repository.remotes; + + if (remotes.length === 0) { + window.showErrorMessage(localize('no remotes added', "Your repository has no remotes.")); + return; + } + + const picks = remotes.map(r => r.name); + const placeHolder = localize('remove remote', "Pick a remote to remove"); + + const remoteName = await window.showQuickPick(picks, { placeHolder }); + + if (!remoteName) { + return; + } + + await repository.removeRemote(remoteName); + } + private async _sync(repository: Repository, rebase: boolean): Promise { const HEAD = repository.HEAD; - if (!HEAD || !HEAD.upstream) { + if (!HEAD) { + return; + } else if (!HEAD.upstream) { + const branchName = HEAD.name; + const message = localize('confirm publish branch', "The branch '{0}' has no upstream branch. Would you like to publish this branch?", branchName); + const yes = localize('ok', "OK"); + const pick = await window.showWarningMessage(message, { modal: true }, yes); + + if (pick === yes) { + await this.publish(repository); + } return; } @@ -1836,8 +1966,16 @@ export class CommandCenter { } @command('git.sync', { repository: true }) - sync(repository: Repository): Promise { - return this._sync(repository, false); + async sync(repository: Repository): Promise { + try { + await this._sync(repository, false); + } catch (err) { + if (/Cancelled/i.test(err && (err.message || err.stderr || ''))) { + return; + } + + throw err; + } } @command('git._syncAll') @@ -1854,8 +1992,16 @@ export class CommandCenter { } @command('git.syncRebase', { repository: true }) - syncRebase(repository: Repository): Promise { - return this._sync(repository, true); + async syncRebase(repository: Repository): Promise { + try { + await this._sync(repository, true); + } catch (err) { + if (/Cancelled/i.test(err && (err.message || err.stderr || ''))) { + return; + } + + throw err; + } } @command('git.publish', { repository: true }) @@ -2118,6 +2264,7 @@ export class CommandCenter { uri = uri ? uri : (window.activeTextEditor && window.activeTextEditor.document.uri); this.outputChannel.appendLine(`git.getSCMResource.uri ${uri && uri.toString()}`); + for (const r of this.model.repositories.map(r => r.root)) { this.outputChannel.appendLine(`repo root ${r}`); } diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts index 0c27365bc51..9f17b20ee8e 100644 --- a/extensions/git/src/decorationProvider.ts +++ b/extensions/git/src/decorationProvider.ts @@ -20,7 +20,6 @@ class GitIgnoreDecorationProvider implements DecorationProvider { private disposables: Disposable[] = []; constructor(private model: Model) { - //todo@joh -> events when the ignore status actually changes, not only when the file changes this.onDidChangeDecorations = fireEvent(anyEvent( filterEvent(workspace.onDidSaveTextDocument, e => e.fileName.endsWith('.gitignore')), model.onDidOpenRepository, @@ -119,7 +118,7 @@ class GitDecorationProvider implements DecorationProvider { const uris = new Set([...this.decorations.keys()].concat([...newDecorations.keys()])); this.decorations = newDecorations; - this._onDidChangeDecorations.fire([...uris.values()].map(Uri.parse)); + this._onDidChangeDecorations.fire([...uris.values()].map(value => Uri.parse(value, true))); } private collectDecorationData(group: GitResourceGroup, bucket: Map): void { diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 2ed2c487376..b306cab1255 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -11,10 +11,14 @@ import * as which from 'which'; import { EventEmitter } from 'events'; import iconv = require('iconv-lite'); import * as filetype from 'file-type'; -import { assign, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent } from './util'; +import { assign, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter } from './util'; import { CancellationToken } from 'vscode'; +import { URI } from 'vscode-uri'; import { detectEncoding } from './encoding'; -import { Ref, RefType, Branch, Remote, GitErrorCodes } from './api/git'; +import { Ref, RefType, Branch, Remote, GitErrorCodes, LogOptions, Change, Status } from './api/git'; + +// https://github.com/microsoft/vscode/issues/65693 +const MAX_CLI_LENGTH = 30000; const readfile = denodeify(fs.readFile); @@ -306,11 +310,15 @@ function getGitErrorCode(stderr: string): string | undefined { return GitErrorCodes.BranchAlreadyExists; } else if (/'.+' is not a valid branch name/.test(stderr)) { return GitErrorCodes.InvalidBranchName; + } else if (/Please,? commit your changes or stash them/.test(stderr)) { + return GitErrorCodes.DirtyWorkTree; } return undefined; } +const COMMIT_FORMAT = '%H\n%ae\n%P\n%B'; + export class Git { readonly path: string; @@ -324,8 +332,8 @@ export class Git { this.env = options.env || {}; } - open(repository: string): Repository { - return new Repository(this, repository); + open(repository: string, dotGit: string): Repository { + return new Repository(this, repository, dotGit); } async init(repository: string): Promise { @@ -334,7 +342,7 @@ export class Git { } async clone(url: string, parentPath: string, cancellationToken?: CancellationToken): Promise { - let baseFolderName = decodeURI(url).replace(/^.*\//, '').replace(/\.git$/, '') || 'repository'; + let baseFolderName = decodeURI(url).replace(/[\/]+$/, '').replace(/^.*[\/\\]/, '').replace(/\.git$/, '') || 'repository'; let folderName = baseFolderName; let folderPath = path.join(parentPath, folderName); let count = 1; @@ -347,7 +355,7 @@ export class Git { await mkdirp(parentPath); try { - await this.exec(parentPath, ['clone', url, folderPath], { cancellationToken }); + await this.exec(parentPath, ['clone', url.includes(' ') ? encodeURI(url) : url, folderPath], { cancellationToken }); } catch (err) { if (err.stderr) { err.stderr = err.stderr.replace(/^Cloning.+$/m, '').trim(); @@ -365,6 +373,17 @@ export class Git { return path.normalize(result.stdout.trim()); } + async getRepositoryDotGit(repositoryPath: string): Promise { + const result = await this.exec(repositoryPath, ['rev-parse', '--git-dir']); + let dotGitPath = result.stdout.trim(); + + if (!path.isAbsolute(dotGitPath)) { + dotGitPath = path.join(repositoryPath, dotGitPath); + } + + return path.normalize(dotGitPath); + } + async exec(cwd: string, args: string[], options: SpawnOptions = {}): Promise> { options = assign({ cwd }, options || {}); return await this._exec(args, options); @@ -450,6 +469,7 @@ export interface Commit { hash: string; message: string; parents: string[]; + authorEmail?: string | undefined; } export class GitStatusParser { @@ -552,7 +572,7 @@ export function parseGitmodules(raw: string): Submodule[] { return; } - const propertyMatch = /^\s*(\w+) = (.*)$/.exec(line); + const propertyMatch = /^\s*(\w+)\s+=\s+(.*)$/.exec(line); if (!propertyMatch) { return; @@ -581,13 +601,13 @@ export function parseGitmodules(raw: string): Submodule[] { } export function parseGitCommit(raw: string): Commit | null { - const match = /^([0-9a-f]{40})\n(.*)\n([^]*)$/m.exec(raw.trim()); + const match = /^([0-9a-f]{40})\n(.*)\n(.*)\n([^]*)$/m.exec(raw.trim()); if (!match) { return null; } - const parents = match[2] ? match[2].split(' ') : []; - return { hash: match[1], message: match[3], parents }; + const parents = match[3] ? match[3].split(' ') : []; + return { hash: match[1], message: match[4], parents, authorEmail: match[2] }; } interface LsTreeElement { @@ -629,6 +649,12 @@ export interface CommitOptions { empty?: boolean; } +export interface PullOptions { + unshallow?: boolean; + tags?: boolean; + readonly cancellationToken?: CancellationToken; +} + export enum ForcePushMode { Force, ForceWithLease @@ -638,7 +664,8 @@ export class Repository { constructor( private _git: Git, - private repositoryRoot: string + private repositoryRoot: string, + readonly dotGit: string ) { } get git(): Git { @@ -697,6 +724,41 @@ export class Repository { }); } + async log(options?: LogOptions): Promise { + const maxEntries = options && typeof options.maxEntries === 'number' && options.maxEntries > 0 ? options.maxEntries : 32; + const args = ['log', '-' + maxEntries, `--pretty=format:${COMMIT_FORMAT}%x00%x00`]; + const gitResult = await this.run(args); + if (gitResult.exitCode) { + // An empty repo. + return []; + } + + const s = gitResult.stdout; + const result: Commit[] = []; + let index = 0; + while (index < s.length) { + let nextIndex = s.indexOf('\x00\x00', index); + if (nextIndex === -1) { + nextIndex = s.length; + } + + let entry = s.substr(index, nextIndex - index); + if (entry.startsWith('\n')) { + entry = entry.substring(1); + } + + const commit = parseGitCommit(entry); + if (!commit) { + break; + } + + result.push(commit); + index = nextIndex + 2; + } + + return result; + } + async bufferString(object: string, encoding: string = 'utf8', autoGuessEncoding = false): Promise { const stdout = await this.buffer(object); @@ -851,25 +913,53 @@ export class Repository { return result.stdout; } - async diffWithHEAD(path: string): Promise { + diffWithHEAD(): Promise; + diffWithHEAD(path: string): Promise; + diffWithHEAD(path?: string | undefined): Promise; + async diffWithHEAD(path?: string | undefined): Promise { + if (!path) { + return await this.diffFiles(false); + } + const args = ['diff', '--', path]; const result = await this.run(args); return result.stdout; } - async diffWith(ref: string, path: string): Promise { + diffWith(ref: string): Promise; + diffWith(ref: string, path: string): Promise; + diffWith(ref: string, path?: string | undefined): Promise; + async diffWith(ref: string, path?: string): Promise { + if (!path) { + return await this.diffFiles(false, ref); + } + const args = ['diff', ref, '--', path]; const result = await this.run(args); return result.stdout; } - async diffIndexWithHEAD(path: string): Promise { + diffIndexWithHEAD(): Promise; + diffIndexWithHEAD(path: string): Promise; + diffIndexWithHEAD(path?: string | undefined): Promise; + async diffIndexWithHEAD(path?: string): Promise { + if (!path) { + return await this.diffFiles(true); + } + const args = ['diff', '--cached', '--', path]; const result = await this.run(args); return result.stdout; } - async diffIndexWith(ref: string, path: string): Promise { + diffIndexWith(ref: string): Promise; + diffIndexWith(ref: string, path: string): Promise; + diffIndexWith(ref: string, path?: string | undefined): Promise; + async diffIndexWith(ref: string, path?: string): Promise { + if (!path) { + return await this.diffFiles(true, ref); + } + const args = ['diff', '--cached', ref, '--', path]; const result = await this.run(args); return result.stdout; @@ -881,13 +971,102 @@ export class Repository { return result.stdout; } - async diffBetween(ref1: string, ref2: string, path: string): Promise { - const args = ['diff', `${ref1}...${ref2}`, '--', path]; + diffBetween(ref1: string, ref2: string): Promise; + diffBetween(ref1: string, ref2: string, path: string): Promise; + diffBetween(ref1: string, ref2: string, path?: string | undefined): Promise; + async diffBetween(ref1: string, ref2: string, path?: string): Promise { + const range = `${ref1}...${ref2}`; + if (!path) { + return await this.diffFiles(false, range); + } + + const args = ['diff', range, '--', path]; const result = await this.run(args); return result.stdout.trim(); } + private async diffFiles(cached: boolean, ref?: string): Promise { + const args = ['diff', '--name-status', '-z', '--diff-filter=ADMR']; + if (cached) { + args.push('--cached'); + } + + if (ref) { + args.push(ref); + } + + const gitResult = await this.run(args); + if (gitResult.exitCode) { + return []; + } + + const entries = gitResult.stdout.split('\x00'); + let index = 0; + const result: Change[] = []; + + entriesLoop: + while (index < entries.length - 1) { + const change = entries[index++]; + const resourcePath = entries[index++]; + if (!change || !resourcePath) { + break; + } + + const originalUri = URI.file(path.isAbsolute(resourcePath) ? resourcePath : path.join(this.repositoryRoot, resourcePath)); + let status: Status = Status.UNTRACKED; + + // Copy or Rename status comes with a number, e.g. 'R100'. We don't need the number, so we use only first character of the status. + switch (change[0]) { + case 'M': + status = Status.MODIFIED; + break; + + case 'A': + status = Status.INDEX_ADDED; + break; + + case 'D': + status = Status.DELETED; + break; + + // Rename contains two paths, the second one is what the file is renamed/copied to. + case 'R': + if (index >= entries.length) { + break; + } + + const newPath = entries[index++]; + if (!newPath) { + break; + } + + const uri = URI.file(path.isAbsolute(newPath) ? newPath : path.join(this.repositoryRoot, newPath)); + result.push({ + uri, + renameUri: uri, + originalUri, + status: Status.INDEX_RENAMED + }); + + continue; + + default: + // Unknown status + break entriesLoop; + } + + result.push({ + status, + originalUri, + uri: originalUri, + renameUri: originalUri, + }); + } + + return result; + } + async getMergeBase(ref1: string, ref2: string): Promise { const args = ['merge-base', ref1, ref2]; const result = await this.run(args); @@ -963,13 +1142,14 @@ export class Repository { args.push(treeish); } - if (paths && paths.length) { - args.push('--'); - args.push.apply(args, paths); - } - try { - await this.run(args); + if (paths && paths.length > 0) { + for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) { + await this.run([...args, '--', ...chunk]); + } + } else { + await this.run(args); + } } catch (err) { if (/Please,? commit your changes or stash them/.test(err.stderr || '')) { err.gitErrorCode = GitErrorCodes.DirtyWorkTree; @@ -1042,7 +1222,7 @@ export class Repository { } async branch(name: string, checkout: boolean, ref?: string): Promise { - const args = checkout ? ['checkout', '-q', '-b', name] : ['branch', '-q', name]; + const args = checkout ? ['checkout', '-q', '-b', name, '--no-track'] : ['branch', '-q', name]; if (ref) { args.push(ref); @@ -1100,11 +1280,17 @@ export class Repository { async clean(paths: string[]): Promise { const pathsByGroup = groupBy(paths, p => path.dirname(p)); const groups = Object.keys(pathsByGroup).map(k => pathsByGroup[k]); - const tasks = groups.map(paths => () => this.run(['clean', '-f', '-q', '--'].concat(paths))); - for (let task of tasks) { - await task(); + const limiter = new Limiter(5); + const promises: Promise[] = []; + + for (const paths of groups) { + for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) { + promises.push(limiter.queue(() => this.run(['clean', '-f', '-q', '--', ...chunk]))); + } } + + await Promise.all(promises); } async undo(): Promise { @@ -1166,7 +1352,7 @@ export class Repository { await this.run(args); } - async fetch(options: { remote?: string, ref?: string, all?: boolean, prune?: boolean } = {}): Promise { + async fetch(options: { remote?: string, ref?: string, all?: boolean, prune?: boolean, depth?: number } = {}): Promise { const args = ['fetch']; if (options.remote) { @@ -1183,6 +1369,9 @@ export class Repository { args.push('--prune'); } + if (typeof options.depth === 'number') { + args.push(`--depth=${options.depth}`); + } try { await this.run(args); @@ -1197,8 +1386,16 @@ export class Repository { } } - async pull(rebase?: boolean, remote?: string, branch?: string): Promise { - const args = ['pull', '--tags']; + async pull(rebase?: boolean, remote?: string, branch?: string, options: PullOptions = {}): Promise { + const args = ['pull']; + + if (options.tags) { + args.push('--tags'); + } + + if (options.unshallow) { + args.push('--unshallow'); + } if (rebase) { args.push('-r'); @@ -1210,7 +1407,7 @@ export class Repository { } try { - await this.run(args); + await this.run(args, options); } catch (err) { if (/^CONFLICT \([^)]+\): \b/m.test(err.stdout || '')) { err.gitErrorCode = GitErrorCodes.Conflict; @@ -1245,7 +1442,7 @@ export class Repository { } if (tags) { - args.push('--tags'); + args.push('--follow-tags'); } if (remote) { @@ -1271,16 +1468,33 @@ export class Repository { } } + async blame(path: string): Promise { + try { + const args = ['blame']; + args.push(path); + + let result = await this.run(args); + + return result.stdout.trim(); + } catch (err) { + if (/^fatal: no such path/.test(err.stderr || '')) { + err.gitErrorCode = GitErrorCodes.NoPathFound; + } + + throw err; + } + } + async createStash(message?: string, includeUntracked?: boolean): Promise { try { - const args = ['stash', 'save']; + const args = ['stash', 'push']; if (includeUntracked) { args.push('-u'); } if (message) { - args.push('--', message); + args.push('-m', message); } await this.run(args); @@ -1388,6 +1602,14 @@ export class Repository { } } + async findTrackingBranches(upstreamBranch: string): Promise { + const result = await this.run(['for-each-ref', '--format', '%(refname:short)%00%(upstream:short)', 'refs/heads']); + return result.stdout.trim().split('\n') + .map(line => line.trim().split('\0')) + .filter(([_, upstream]) => upstream === upstreamBranch) + .map(([ref]) => ({ name: ref, type: RefType.Head } as Branch)); + } + async getRefs(): Promise { const result = await this.run(['for-each-ref', '--format', '%(refname) %(objectname)', '--sort', '-committerdate']); @@ -1532,13 +1754,16 @@ export class Repository { } async getCommit(ref: string): Promise { - const result = await this.run(['show', '-s', '--format=%H\n%P\n%B', ref]); + const result = await this.run(['show', '-s', `--format=${COMMIT_FORMAT}`, ref]); return parseGitCommit(result.stdout) || Promise.reject('bad commit format'); } async updateSubmodules(paths: string[]): Promise { - const args = ['submodule', 'update', '--', ...paths]; - await this.run(args); + const args = ['submodule', 'update', '--']; + + for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) { + await this.run([...args, ...chunk]); + } } async getSubmodules(): Promise { diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index 22c690a5dfd..da6a940428e 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -12,7 +12,7 @@ import * as path from 'path'; import * as fs from 'fs'; import * as nls from 'vscode-nls'; import { fromGitUri } from './uri'; -import { GitErrorCodes } from './api/git'; +import { GitErrorCodes, APIState as State } from './api/git'; const localize = nls.loadMessageBundle(); @@ -63,26 +63,41 @@ export class Model { private possibleGitRepositoryPaths = new Set(); + private _onDidChangeState = new EventEmitter(); + readonly onDidChangeState = this._onDidChangeState.event; + + private _state: State = 'uninitialized'; + get state(): State { return this._state; } + + setState(state: State): void { + this._state = state; + this._onDidChangeState.fire(state); + } + private disposables: Disposable[] = []; constructor(readonly git: Git, private globalState: Memento, private outputChannel: OutputChannel) { workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables); - this.onDidChangeWorkspaceFolders({ added: workspace.workspaceFolders || [], removed: [] }); - window.onDidChangeVisibleTextEditors(this.onDidChangeVisibleTextEditors, this, this.disposables); - this.onDidChangeVisibleTextEditors(window.visibleTextEditors); - workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.disposables); const fsWatcher = workspace.createFileSystemWatcher('**'); this.disposables.push(fsWatcher); const onWorkspaceChange = anyEvent(fsWatcher.onDidChange, fsWatcher.onDidCreate, fsWatcher.onDidDelete); - const onGitRepositoryChange = filterEvent(onWorkspaceChange, uri => /\/\.git\//.test(uri.path)); + const onGitRepositoryChange = filterEvent(onWorkspaceChange, uri => /\/\.git/.test(uri.path)); const onPossibleGitRepositoryChange = filterEvent(onGitRepositoryChange, uri => !this.getRepository(uri)); onPossibleGitRepositoryChange(this.onPossibleGitRepositoryChange, this, this.disposables); - this.scanWorkspaceFolders(); + this.doInitialScan().finally(() => this.setState('initialized')); + } + + private async doInitialScan(): Promise { + await Promise.all([ + this.onDidChangeWorkspaceFolders({ added: workspace.workspaceFolders || [], removed: [] }), + this.onDidChangeVisibleTextEditors(window.visibleTextEditors), + this.scanWorkspaceFolders() + ]); } /** @@ -157,8 +172,8 @@ export class Model { .filter(r => !activeRepositories.has(r!.repository)) .filter(r => !(workspace.workspaceFolders || []).some(f => isDescendant(f.uri.fsPath, r!.repository.root))) as OpenRepository[]; - possibleRepositoryFolders.forEach(p => this.openRepository(p.uri.fsPath)); openRepositoriesToDispose.forEach(r => r.dispose()); + await Promise.all(possibleRepositoryFolders.map(p => this.openRepository(p.uri.fsPath))); } private onDidChangeConfiguration(): void { @@ -175,7 +190,7 @@ export class Model { openRepositoriesToDispose.forEach(r => r.dispose()); } - private onDidChangeVisibleTextEditors(editors: TextEditor[]): void { + private async onDidChangeVisibleTextEditors(editors: TextEditor[]): Promise { const config = workspace.getConfiguration('git'); const autoRepositoryDetection = config.get('autoRepositoryDetection'); @@ -183,7 +198,7 @@ export class Model { return; } - editors.forEach(editor => { + await Promise.all(editors.map(async editor => { const uri = editor.document.uri; if (uri.scheme !== 'file') { @@ -196,8 +211,8 @@ export class Model { return; } - this.openRepository(path.dirname(uri.fsPath)); - }); + await this.openRepository(path.dirname(uri.fsPath)); + })); } @sequentialize @@ -232,9 +247,11 @@ export class Model { return; } - const repository = new Repository(this.git.open(repositoryRoot), this.globalState); + const dotGit = await this.git.getRepositoryDotGit(repositoryRoot); + const repository = new Repository(this.git.open(repositoryRoot, dotGit), this.globalState, this.outputChannel); this.open(repository); + await repository.status(); } catch (err) { if (err.gitErrorCode === GitErrorCodes.NotAGitRepository) { return; @@ -420,4 +437,4 @@ export class Model { this.possibleGitRepositoryPaths.clear(); this.disposables = dispose(this.disposables); } -} \ No newline at end of file +} diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 6a57806ac12..07dc1c231e8 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { commands, Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, SourceControlInputBoxValidation, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData, Memento, SourceControlInputBoxValidationType } from 'vscode'; +import { commands, Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, SourceControlInputBoxValidation, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData, Memento, SourceControlInputBoxValidationType, OutputChannel, LogLevel, env, ProgressOptions, CancellationToken } from 'vscode'; import { Repository as BaseRepository, Commit, Stash, GitError, Submodule, CommitOptions, ForcePushMode } from './git'; -import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent } from './util'; +import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent, combinedDisposable } from './util'; import { memoize, throttle, debounce } from './decorators'; import { toGitUri } from './uri'; import { AutoFetcher } from './autofetch'; @@ -13,7 +13,8 @@ import * as path from 'path'; import * as nls from 'vscode-nls'; import * as fs from 'fs'; import { StatusBarCommands } from './statusbar'; -import { Branch, Ref, Remote, RefType, GitErrorCodes, Status } from './api/git'; +import { Branch, Ref, Remote, RefType, GitErrorCodes, Status, LogOptions, Change } from './api/git'; +import { IFileWatcher, watch } from './watch'; const timeout = (millis: number) => new Promise(c => setTimeout(c, millis)); @@ -206,7 +207,7 @@ export class Resource implements SourceControlResourceState { case Status.INDEX_ADDED: case Status.INTENT_TO_ADD: return new ThemeColor('gitDecoration.addedResourceForeground'); - case Status.INDEX_RENAMED: // todo@joh - special color? + case Status.INDEX_RENAMED: case Status.UNTRACKED: return new ThemeColor('gitDecoration.untrackedResourceForeground'); case Status.IGNORED: @@ -299,7 +300,10 @@ export const enum Operation { GetObjectDetails = 'GetObjectDetails', SubmoduleUpdate = 'SubmoduleUpdate', RebaseContinue = 'RebaseContinue', - Apply = 'Apply' + FindTrackingBranches = 'GetTracking', + Apply = 'Apply', + Blame = 'Blame', + Log = 'Log', } function isReadOnly(operation: Operation): boolean { @@ -444,6 +448,91 @@ class ProgressManager { } } +class FileEventLogger { + + private eventDisposable: IDisposable = EmptyDisposable; + private logLevelDisposable: IDisposable = EmptyDisposable; + + constructor( + private onWorkspaceWorkingTreeFileChange: Event, + private onDotGitFileChange: Event, + private outputChannel: OutputChannel + ) { + this.logLevelDisposable = env.onDidChangeLogLevel(this.onDidChangeLogLevel, this); + this.onDidChangeLogLevel(env.logLevel); + } + + private onDidChangeLogLevel(level: LogLevel): void { + this.eventDisposable.dispose(); + + if (level > LogLevel.Debug) { + return; + } + + this.eventDisposable = combinedDisposable([ + this.onWorkspaceWorkingTreeFileChange(uri => this.outputChannel.appendLine(`[debug] [wt] Change: ${uri.fsPath}`)), + this.onDotGitFileChange(uri => this.outputChannel.appendLine(`[debug] [.git] Change: ${uri.fsPath}`)) + ]); + } + + dispose(): void { + this.eventDisposable.dispose(); + this.logLevelDisposable.dispose(); + } +} + +class DotGitWatcher implements IFileWatcher { + + readonly event: Event; + + private emitter = new EventEmitter(); + private transientDisposables: IDisposable[] = []; + private disposables: IDisposable[] = []; + + constructor( + private repository: Repository, + private outputChannel: OutputChannel + ) { + const rootWatcher = watch(repository.dotGit); + this.disposables.push(rootWatcher); + + const filteredRootWatcher = filterEvent(rootWatcher.event, uri => !/\/\.git(\/index\.lock)?$/.test(uri.path)); + this.event = anyEvent(filteredRootWatcher, this.emitter.event); + + repository.onDidRunGitStatus(this.updateTransientWatchers, this, this.disposables); + this.updateTransientWatchers(); + } + + private updateTransientWatchers() { + this.transientDisposables = dispose(this.transientDisposables); + + if (!this.repository.HEAD || !this.repository.HEAD.upstream) { + return; + } + + this.transientDisposables = dispose(this.transientDisposables); + + const { name, remote } = this.repository.HEAD.upstream; + const upstreamPath = path.join(this.repository.dotGit, 'refs', 'remotes', remote, name); + + try { + const upstreamWatcher = watch(upstreamPath); + this.transientDisposables.push(upstreamWatcher); + upstreamWatcher.event(this.emitter.fire, this.emitter, this.transientDisposables); + } catch (err) { + if (env.logLevel <= LogLevel.Error) { + this.outputChannel.appendLine(`Failed to watch ref '${upstreamPath}', is most likely packed.\n${err.stack || err}`); + } + } + } + + dispose() { + this.emitter.dispose(); + this.transientDisposables = dispose(this.transientDisposables); + this.disposables = dispose(this.disposables); + } +} + export class Repository implements Disposable { private _onDidChangeRepository = new EventEmitter(); @@ -541,36 +630,52 @@ export class Repository implements Disposable { return this.repository.root; } + get dotGit(): string { + return this.repository.dotGit; + } + private isRepositoryHuge = false; private didWarnAboutLimit = false; private isFreshRepository: boolean | undefined = undefined; + private disposables: Disposable[] = []; constructor( private readonly repository: BaseRepository, - globalState: Memento + globalState: Memento, + outputChannel: OutputChannel ) { - const fsWatcher = workspace.createFileSystemWatcher('**'); - this.disposables.push(fsWatcher); + const workspaceWatcher = workspace.createFileSystemWatcher('**'); + this.disposables.push(workspaceWatcher); - const workspaceFilter = (uri: Uri) => isDescendant(repository.root, uri.fsPath); - const onWorkspaceDelete = filterEvent(fsWatcher.onDidDelete, workspaceFilter); - const onWorkspaceChange = filterEvent(anyEvent(fsWatcher.onDidChange, fsWatcher.onDidCreate), workspaceFilter); - const onRepositoryDotGitDelete = filterEvent(onWorkspaceDelete, uri => /\/\.git$/.test(uri.path)); - const onRepositoryChange = anyEvent(onWorkspaceDelete, onWorkspaceChange); + const onWorkspaceFileChange = anyEvent(workspaceWatcher.onDidChange, workspaceWatcher.onDidCreate, workspaceWatcher.onDidDelete); + const onWorkspaceRepositoryFileChange = filterEvent(onWorkspaceFileChange, uri => isDescendant(repository.root, uri.fsPath)); + const onWorkspaceWorkingTreeFileChange = filterEvent(onWorkspaceRepositoryFileChange, uri => !/\/\.git($|\/)/.test(uri.path)); - // relevant repository changes are: - // - DELETE .git folder - // - ANY CHANGE within .git folder except .git itself and .git/index.lock - const onRelevantRepositoryChange = anyEvent( - onRepositoryDotGitDelete, - filterEvent(onRepositoryChange, uri => !/\/\.git(\/index\.lock)?$/.test(uri.path)) - ); + let onDotGitFileChange: Event; - onRelevantRepositoryChange(this.onFSChange, this, this.disposables); + try { + const dotGitFileWatcher = new DotGitWatcher(this, outputChannel); + onDotGitFileChange = dotGitFileWatcher.event; + this.disposables.push(dotGitFileWatcher); + } catch (err) { + if (env.logLevel <= LogLevel.Error) { + outputChannel.appendLine(`Failed to watch '${this.dotGit}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`); + } - const onRelevantGitChange = filterEvent(onRelevantRepositoryChange, uri => /\/\.git\//.test(uri.path)); - onRelevantGitChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables); + onDotGitFileChange = filterEvent(onWorkspaceRepositoryFileChange, uri => /\/\.git($|\/)/.test(uri.path)); + } + + // FS changes should trigger `git status`: + // - any change inside the repository working tree + // - any change whithin the first level of the `.git` folder, except the folder itself and `index.lock` + const onFileChange = anyEvent(onWorkspaceWorkingTreeFileChange, onDotGitFileChange); + onFileChange(this.onFileChange, this, this.disposables); + + // Relevate repository changes should trigger virtual document change events + onDotGitFileChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables); + + this.disposables.push(new FileEventLogger(onWorkspaceWorkingTreeFileChange, onDotGitFileChange, outputChannel)); const root = Uri.file(repository.root); this._sourceControl = scm.createSourceControl('git', 'Git', root); @@ -580,9 +685,9 @@ export class Repository implements Disposable { this._sourceControl.inputBox.validateInput = this.validateInput.bind(this); this.disposables.push(this._sourceControl); - this._mergeGroup = this._sourceControl.createResourceGroup('merge', localize('merge changes', "Merge Changes")); - this._indexGroup = this._sourceControl.createResourceGroup('index', localize('staged changes', "Staged Changes")); - this._workingTreeGroup = this._sourceControl.createResourceGroup('workingTree', localize('changes', "Changes")); + this._mergeGroup = this._sourceControl.createResourceGroup('merge', localize('merge changes', "MERGE CHANGES")); + this._indexGroup = this._sourceControl.createResourceGroup('index', localize('staged changes', "STAGED CHANGES")); + this._workingTreeGroup = this._sourceControl.createResourceGroup('workingTree', localize('changes', "CHANGES")); const updateIndexGroupVisibility = () => { const config = workspace.getConfiguration('git', root); @@ -620,7 +725,6 @@ export class Repository implements Disposable { this.disposables.push(progressManager); this.updateCommitTemplate(); - this.status(); } validateInput(text: string, position: number): SourceControlInputBoxValidation | undefined { @@ -671,20 +775,6 @@ export class Repository implements Disposable { } } - - - - - - - - - - // const subjectThreshold = - - - // Math.max(config.get('inputValidationLength') || 50, config.get('subjectValidationLength') || 50, 0) || 50; - if (line.length <= threshold) { if (setting !== 'always') { return; @@ -726,10 +816,18 @@ export class Repository implements Disposable { return this.run(Operation.Config, () => this.repository.config('local', key)); } + getGlobalConfig(key: string): Promise { + return this.run(Operation.Config, () => this.repository.config('global', key)); + } + setConfig(key: string, value: string): Promise { return this.run(Operation.Config, () => this.repository.config('local', key, value)); } + log(options?: LogOptions): Promise { + return this.run(Operation.Log, () => this.repository.log(options)); + } + @throttle async status(): Promise { await this.run(Operation.Status); @@ -739,19 +837,31 @@ export class Repository implements Disposable { return this.run(Operation.Diff, () => this.repository.diff(cached)); } - diffWithHEAD(path: string): Promise { + diffWithHEAD(): Promise; + diffWithHEAD(path: string): Promise; + diffWithHEAD(path?: string | undefined): Promise; + diffWithHEAD(path?: string | undefined): Promise { return this.run(Operation.Diff, () => this.repository.diffWithHEAD(path)); } - diffWith(ref: string, path: string): Promise { + diffWith(ref: string): Promise; + diffWith(ref: string, path: string): Promise; + diffWith(ref: string, path?: string | undefined): Promise; + diffWith(ref: string, path?: string): Promise { return this.run(Operation.Diff, () => this.repository.diffWith(ref, path)); } - diffIndexWithHEAD(path: string): Promise { + diffIndexWithHEAD(): Promise; + diffIndexWithHEAD(path: string): Promise; + diffIndexWithHEAD(path?: string | undefined): Promise; + diffIndexWithHEAD(path?: string): Promise { return this.run(Operation.Diff, () => this.repository.diffIndexWithHEAD(path)); } - diffIndexWith(ref: string, path: string): Promise { + diffIndexWith(ref: string): Promise; + diffIndexWith(ref: string, path: string): Promise; + diffIndexWith(ref: string, path?: string | undefined): Promise; + diffIndexWith(ref: string, path?: string): Promise { return this.run(Operation.Diff, () => this.repository.diffIndexWith(ref, path)); } @@ -759,7 +869,10 @@ export class Repository implements Disposable { return this.run(Operation.Diff, () => this.repository.diffBlobs(object1, object2)); } - diffBetween(ref1: string, ref2: string, path: string): Promise { + diffBetween(ref1: string, ref2: string): Promise; + diffBetween(ref1: string, ref2: string, path: string): Promise; + diffBetween(ref1: string, ref2: string, path?: string | undefined): Promise; + diffBetween(ref1: string, ref2: string, path?: string): Promise { return this.run(Operation.Diff, () => this.repository.diffBetween(ref1, ref2, path)); } @@ -844,21 +957,9 @@ export class Repository implements Disposable { } }); - const promises: Promise[] = []; - - if (toClean.length > 0) { - promises.push(this.repository.clean(toClean)); - } - - if (toCheckout.length > 0) { - promises.push(this.repository.checkout('', toCheckout)); - } - - if (submodulesToUpdate.length > 0) { - promises.push(this.repository.updateSubmodules(submodulesToUpdate)); - } - - await Promise.all(promises); + await this.repository.clean(toClean); + await this.repository.checkout('', toCheckout); + await this.repository.updateSubmodules(submodulesToUpdate); }); } @@ -898,6 +999,10 @@ export class Repository implements Disposable { await this.run(Operation.CheckoutTracking, () => this.repository.checkout(treeish, [], { track: true })); } + async findTrackingBranches(upstreamRef: string): Promise { + return await this.run(Operation.FindTrackingBranches, () => this.repository.findTrackingBranches(upstreamRef)); + } + async getCommit(ref: string): Promise { return await this.repository.getCommit(ref); } @@ -933,8 +1038,8 @@ export class Repository implements Disposable { await this.run(Operation.Fetch, () => this.repository.fetch({ all: true })); } - async fetch(remote?: string, ref?: string): Promise { - await this.run(Operation.Fetch, () => this.repository.fetch({ remote, ref })); + async fetch(remote?: string, ref?: string, depth?: number): Promise { + await this.run(Operation.Fetch, () => this.repository.fetch({ remote, ref, depth })); } @throttle @@ -951,7 +1056,7 @@ export class Repository implements Disposable { } @throttle - async pull(head?: Branch): Promise { + async pull(head?: Branch, unshallow?: boolean): Promise { let remote: string | undefined; let branch: string | undefined; @@ -960,19 +1065,20 @@ export class Repository implements Disposable { branch = `${head.upstream.name}`; } - return this.pullFrom(false, remote, branch); + return this.pullFrom(false, remote, branch, unshallow); } - async pullFrom(rebase?: boolean, remote?: string, branch?: string): Promise { + async pullFrom(rebase?: boolean, remote?: string, branch?: string, unshallow?: boolean): Promise { await this.run(Operation.Pull, async () => { await this.maybeAutoStash(async () => { const config = workspace.getConfiguration('git', Uri.file(this.root)); const fetchOnPull = config.get('fetchOnPull'); + const tags = config.get('pullTags'); if (fetchOnPull) { - await this.repository.pull(rebase); + await this.repository.pull(rebase, undefined, undefined, { unshallow, tags }); } else { - await this.repository.pull(rebase, remote, branch); + await this.repository.pull(rebase, remote, branch, { unshallow, tags }); } }); }); @@ -995,10 +1101,14 @@ export class Repository implements Disposable { await this.run(Operation.Push, () => this.repository.push(remote, name, setUpstream, undefined, forcePushMode)); } - async pushTags(remote?: string, forcePushMode?: ForcePushMode): Promise { + async pushFollowTags(remote?: string, forcePushMode?: ForcePushMode): Promise { await this.run(Operation.Push, () => this.repository.push(remote, undefined, false, true, forcePushMode)); } + async blame(path: string): Promise { + return await this.run(Operation.Blame, () => this.repository.blame(path)); + } + @throttle sync(head: Branch): Promise { return this._sync(head, false); @@ -1024,11 +1134,23 @@ export class Repository implements Disposable { await this.maybeAutoStash(async () => { const config = workspace.getConfiguration('git', Uri.file(this.root)); const fetchOnPull = config.get('fetchOnPull'); + const tags = config.get('pullTags'); + const supportCancellation = config.get('supportCancellation'); - if (fetchOnPull) { - await this.repository.pull(rebase); + const fn = fetchOnPull + ? async (cancellationToken?: CancellationToken) => await this.repository.pull(rebase, undefined, undefined, { tags, cancellationToken }) + : async (cancellationToken?: CancellationToken) => await this.repository.pull(rebase, remoteName, pullBranch, { tags, cancellationToken }); + + if (supportCancellation) { + const opts: ProgressOptions = { + location: ProgressLocation.Notification, + title: localize('sync is unpredictable', "Syncing. Cancelling may cause serious damages to the repository"), + cancellable: true + }; + + await window.withProgress(opts, (_, token) => fn(token)); } else { - await this.repository.pull(rebase, remoteName, pullBranch); + await fn(); } const remote = this.remotes.find(r => r.name === remoteName); @@ -1141,7 +1263,7 @@ export class Repository implements Disposable { } // https://git-scm.com/docs/git-check-ignore#git-check-ignore--z - const child = this.repository.stream(['check-ignore', '-z', '--stdin'], { stdio: [null, null, null] }); + const child = this.repository.stream(['check-ignore', '-v', '-z', '--stdin'], { stdio: [null, null, null] }); child.stdin.end(filePaths.join('\0'), 'utf8'); const onExit = (exitCode: number) => { @@ -1149,8 +1271,7 @@ export class Repository implements Disposable { // nothing ignored resolve(new Set()); } else if (exitCode === 0) { - // paths are separated by the null-character - resolve(new Set(data.split('\0'))); + resolve(new Set(this.parseIgnoreCheck(data))); } else { if (/ is in submodule /.test(stderr)) { reject(new GitError({ stdout: data, stderr, exitCode, gitErrorCode: GitErrorCodes.IsInSubmodule })); @@ -1178,6 +1299,23 @@ export class Repository implements Disposable { }); } + // Parses output of `git check-ignore -v -z` and returns only those paths + // that are actually ignored by git. + // Matches to a negative pattern (starting with '!') are filtered out. + // See also https://git-scm.com/docs/git-check-ignore#_output. + private parseIgnoreCheck(raw: string): string[] { + const ignored = []; + const elements = raw.split('\0'); + for (let i = 0; i < elements.length; i += 4) { + const pattern = elements[i + 2]; + const path = elements[i + 3]; + if (pattern && !pattern.startsWith('!')) { + ignored.push(path); + } + } + return ignored; + } + private async run(operation: Operation, runOperation: () => Promise = () => Promise.resolve(null)): Promise { if (this.state !== RepositoryState.Idle) { throw new Error('Repository not initialized'); @@ -1415,7 +1553,7 @@ export class Repository implements Disposable { return result; } - private onFSChange(_uri: Uri): void { + private onFileChange(_uri: Uri): void { const config = workspace.getConfiguration('git'); const autorefresh = config.get('autorefresh'); diff --git a/extensions/git/src/test/git.test.ts b/extensions/git/src/test/git.test.ts index 6b7af8c8684..a860c82352a 100644 --- a/extensions/git/src/test/git.test.ts +++ b/extensions/git/src/test/git.test.ts @@ -6,6 +6,7 @@ import 'mocha'; import { GitStatusParser, parseGitCommit, parseGitmodules, parseLsTree, parseLsFiles } from '../git'; import * as assert from 'assert'; +import { splitInChunks } from '../util'; suite('git', () => { suite('GitStatusParser', () => { @@ -172,42 +173,59 @@ suite('git', () => { { name: 'deps/spdlog4', path: 'deps/spdlog4', url: 'https://github.com/gabime/spdlog4.git' } ]); }); + + test('whitespace #74844', () => { + const sample = `[submodule "deps/spdlog"] + path = deps/spdlog + url = https://github.com/gabime/spdlog.git +`; + + assert.deepEqual(parseGitmodules(sample), [ + { name: 'deps/spdlog', path: 'deps/spdlog', url: 'https://github.com/gabime/spdlog.git' } + ]); + }); }); suite('parseGitCommit', () => { test('single parent commit', function () { const GIT_OUTPUT_SINGLE_PARENT = `52c293a05038d865604c2284aa8698bd087915a1 +john.doe@mail.com 8e5a374372b8393906c7e380dbb09349c5385554 This is a commit message.`; assert.deepEqual(parseGitCommit(GIT_OUTPUT_SINGLE_PARENT), { hash: '52c293a05038d865604c2284aa8698bd087915a1', message: 'This is a commit message.', - parents: ['8e5a374372b8393906c7e380dbb09349c5385554'] + parents: ['8e5a374372b8393906c7e380dbb09349c5385554'], + authorEmail: 'john.doe@mail.com', }); }); test('multiple parent commits', function () { const GIT_OUTPUT_MULTIPLE_PARENTS = `52c293a05038d865604c2284aa8698bd087915a1 +john.doe@mail.com 8e5a374372b8393906c7e380dbb09349c5385554 df27d8c75b129ab9b178b386077da2822101b217 This is a commit message.`; assert.deepEqual(parseGitCommit(GIT_OUTPUT_MULTIPLE_PARENTS), { hash: '52c293a05038d865604c2284aa8698bd087915a1', message: 'This is a commit message.', - parents: ['8e5a374372b8393906c7e380dbb09349c5385554', 'df27d8c75b129ab9b178b386077da2822101b217'] + parents: ['8e5a374372b8393906c7e380dbb09349c5385554', 'df27d8c75b129ab9b178b386077da2822101b217'], + authorEmail: 'john.doe@mail.com', }); }); test('no parent commits', function () { const GIT_OUTPUT_NO_PARENTS = `52c293a05038d865604c2284aa8698bd087915a1 +john.doe@mail.com This is a commit message.`; assert.deepEqual(parseGitCommit(GIT_OUTPUT_NO_PARENTS), { hash: '52c293a05038d865604c2284aa8698bd087915a1', message: 'This is a commit message.', - parents: [] + parents: [], + authorEmail: 'john.doe@mail.com', }); }); }); @@ -275,4 +293,78 @@ This is a commit message.`; ]); }); }); -}); \ No newline at end of file + + suite('splitInChunks', () => { + test('unit tests', function () { + assert.deepEqual( + [...splitInChunks(['hello', 'there', 'cool', 'stuff'], 6)], + [['hello'], ['there'], ['cool'], ['stuff']] + ); + + assert.deepEqual( + [...splitInChunks(['hello', 'there', 'cool', 'stuff'], 10)], + [['hello', 'there'], ['cool', 'stuff']] + ); + + assert.deepEqual( + [...splitInChunks(['hello', 'there', 'cool', 'stuff'], 12)], + [['hello', 'there'], ['cool', 'stuff']] + ); + + assert.deepEqual( + [...splitInChunks(['hello', 'there', 'cool', 'stuff'], 14)], + [['hello', 'there', 'cool'], ['stuff']] + ); + + assert.deepEqual( + [...splitInChunks(['hello', 'there', 'cool', 'stuff'], 2000)], + [['hello', 'there', 'cool', 'stuff']] + ); + + assert.deepEqual( + [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 1)], + [['0'], ['01'], ['012'], ['0'], ['01'], ['012'], ['0'], ['01'], ['012']] + ); + + assert.deepEqual( + [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 2)], + [['0'], ['01'], ['012'], ['0'], ['01'], ['012'], ['0'], ['01'], ['012']] + ); + + assert.deepEqual( + [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 3)], + [['0', '01'], ['012'], ['0', '01'], ['012'], ['0', '01'], ['012']] + ); + + assert.deepEqual( + [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 4)], + [['0', '01'], ['012', '0'], ['01'], ['012', '0'], ['01'], ['012']] + ); + + assert.deepEqual( + [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 5)], + [['0', '01'], ['012', '0'], ['01', '012'], ['0', '01'], ['012']] + ); + + assert.deepEqual( + [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 6)], + [['0', '01', '012'], ['0', '01', '012'], ['0', '01', '012']] + ); + + assert.deepEqual( + [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 7)], + [['0', '01', '012', '0'], ['01', '012', '0'], ['01', '012']] + ); + + assert.deepEqual( + [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 8)], + [['0', '01', '012', '0'], ['01', '012', '0', '01'], ['012']] + ); + + assert.deepEqual( + [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 9)], + [['0', '01', '012', '0', '01'], ['012', '0', '01', '012']] + ); + }); + }); +}); diff --git a/extensions/git/src/util.ts b/extensions/git/src/util.ts index 7bf81adccd9..d2e201ca01d 100644 --- a/extensions/git/src/util.ts +++ b/extensions/git/src/util.ts @@ -343,4 +343,71 @@ export function pathEquals(a: string, b: string): boolean { } return a === b; -} \ No newline at end of file +} + +export function* splitInChunks(array: string[], maxChunkLength: number): IterableIterator { + let current: string[] = []; + let length = 0; + + for (const value of array) { + let newLength = length + value.length; + + if (newLength > maxChunkLength && current.length > 0) { + yield current; + current = []; + newLength = value.length; + } + + current.push(value); + length = newLength; + } + + if (current.length > 0) { + yield current; + } +} + +interface ILimitedTaskFactory { + factory: () => Promise; + c: (value?: T | Promise) => void; + e: (error?: any) => void; +} + +export class Limiter { + + private runningPromises: number; + private maxDegreeOfParalellism: number; + private outstandingPromises: ILimitedTaskFactory[]; + + constructor(maxDegreeOfParalellism: number) { + this.maxDegreeOfParalellism = maxDegreeOfParalellism; + this.outstandingPromises = []; + this.runningPromises = 0; + } + + queue(factory: () => Promise): Promise { + return new Promise((c, e) => { + this.outstandingPromises.push({ factory, c, e }); + this.consume(); + }); + } + + private consume(): void { + while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) { + const iLimitedTask = this.outstandingPromises.shift()!; + this.runningPromises++; + + const promise = iLimitedTask.factory(); + promise.then(iLimitedTask.c, iLimitedTask.e); + promise.then(() => this.consumed(), () => this.consumed()); + } + } + + private consumed(): void { + this.runningPromises--; + + if (this.outstandingPromises.length > 0) { + this.consume(); + } + } +} diff --git a/extensions/git/src/watch.ts b/extensions/git/src/watch.ts new file mode 100644 index 00000000000..c6670cfa884 --- /dev/null +++ b/extensions/git/src/watch.ts @@ -0,0 +1,25 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event, EventEmitter, Uri } from 'vscode'; +import { join } from 'path'; +import * as fs from 'fs'; +import { IDisposable } from './util'; + +export interface IFileWatcher extends IDisposable { + readonly event: Event; +} + +export function watch(location: string): IFileWatcher { + const dotGitWatcher = fs.watch(location); + const onDotGitFileChangeEmitter = new EventEmitter(); + dotGitWatcher.on('change', (_, e) => onDotGitFileChangeEmitter.fire(Uri.file(join(location, e as string)))); + dotGitWatcher.on('error', err => console.error(err)); + + return new class implements IFileWatcher { + event = onDotGitFileChangeEmitter.event; + dispose() { dotGitWatcher.close(); } + }; +} diff --git a/extensions/git/syntaxes/git-rebase.tmLanguage.json b/extensions/git/syntaxes/git-rebase.tmLanguage.json index a2c116bd09b..0238d8a6f29 100644 --- a/extensions/git/syntaxes/git-rebase.tmLanguage.json +++ b/extensions/git/syntaxes/git-rebase.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/textmate/git.tmbundle/commit/3f6ad2138200db14b57a090ecb2d2e733275ca3e", + "version": "https://github.com/textmate/git.tmbundle/commit/5870cf3f8abad3a6637bdf69250b5d2ded427dc4", "name": "Git Rebase Message", "scopeName": "text.git-rebase", "patterns": [ @@ -47,6 +47,15 @@ }, "match": "^\\s*(exec|x)\\s+(.*)$", "name": "meta.commit-command.git-rebase" + }, + { + "captures": { + "1": { + "name": "support.function.git-rebase" + } + }, + "match": "^\\s*(break|b)\\s*$", + "name": "meta.commit-command.git-rebase" } ] } \ No newline at end of file diff --git a/extensions/git/yarn.lock b/extensions/git/yarn.lock index 616d42caddf..1f2ea8aed42 100644 --- a/extensions/git/yarn.lock +++ b/extensions/git/yarn.lock @@ -26,20 +26,20 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb" integrity sha512-El3+WJk2D/ppWNd2X05aiP5l2k4EwF7KwheknQZls+I26eSICoWRhRIJ56jGgw2dqNGQ5LtNajmBU2ajS28EvQ== -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== "@types/which@^1.0.28": version "1.0.28" resolved "https://registry.yarnpkg.com/@types/which/-/which-1.0.28.tgz#016e387629b8817bed653fe32eab5d11279c8df6" integrity sha1-AW44dim4gXvtZT/jLqtdESecjfY= -applicationinsights@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.6.tgz#bc201810de91cea910dab34e8ad35ecde488edeb" - integrity sha512-VQT3kBpJVPw5fCO5n+WUeSx0VHjxFtD7znYbILBlVgOS9/cMDuGFmV2Br3ObzFyZUDGNbEfW36fD1y2/vAiCKw== +applicationinsights@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" + integrity sha512-KzOOGdphOS/lXWMFZe5440LUdFbrLpMvh2SaRxn7BmiI550KAoSb2gIhiq6kJZ9Ir3AxRRztjhzif+e5P5IXIg== dependencies: diagnostic-channel "0.2.0" diagnostic-channel-publishers "0.2.1" @@ -313,18 +313,23 @@ supports-color@3.1.2: dependencies: has-flag "^1.0.0" -vscode-extension-telemetry@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.0.tgz#3cdcb61d03829966bd04b5f11471a1e40d6abaad" - integrity sha512-WVCnP+uLxlqB6UD98yQNV47mR5Rf79LFxpuZhSPhEf0Sb4tPZed3a63n003/dchhOwyCTCBuNN4n8XKJkLEI1Q== +vscode-extension-telemetry@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b" + integrity sha512-TkKKG/B/J94DP5qf6xWB4YaqlhWDg6zbbqVx7Bz//stLQNnfE9XS1xm3f6fl24c5+bnEK0/wHgMgZYKIKxPeUA== dependencies: - applicationinsights "1.0.6" + applicationinsights "1.0.8" vscode-nls@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002" integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw== +vscode-uri@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.0.tgz#2df704222f72b8a71ff266ba0830ed6c51ac1542" + integrity sha512-lWXWofDSYD8r/TIyu64MdwB4FaSirQ608PP/TzUyslyOeHGwQ0eTHUZeJrK1ILOmwUHaJtV693m2JoUYroUDpw== + which@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" diff --git a/extensions/go/language-configuration.json b/extensions/go/language-configuration.json index cf20e02f307..a5e06a56bad 100644 --- a/extensions/go/language-configuration.json +++ b/extensions/go/language-configuration.json @@ -27,5 +27,11 @@ "indentationRules": { "increaseIndentPattern": "^.*(\\bcase\\b.*:|\\bdefault\\b:|(\\b(func|if|else|switch|select|for|struct)\\b.*)?{[^}\"'`]*|\\([^)\"'`]*)$", "decreaseIndentPattern": "^\\s*(\\bcase\\b.*:|\\bdefault\\b:|}[)}]*[),]?|\\)[,]?)$" + }, + "folding": { + "markers": { + "start": "^\\s*//\\s*#?region\\b", + "end": "^\\s*//\\s*#?endregion\\b" + } } } \ No newline at end of file diff --git a/extensions/go/package.json b/extensions/go/package.json index 97aced567ae..a91d729adaf 100644 --- a/extensions/go/package.json +++ b/extensions/go/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js atom/language-go grammars/go.cson ./syntaxes/go.tmLanguage.json" diff --git a/extensions/groovy/cgmanifest.json b/extensions/groovy/cgmanifest.json index 07dec53a640..fc5a3ca9c12 100644 --- a/extensions/groovy/cgmanifest.json +++ b/extensions/groovy/cgmanifest.json @@ -29,4 +29,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/groovy/package.json b/extensions/groovy/package.json index 9cb93f29956..9bed5780419 100644 --- a/extensions/groovy/package.json +++ b/extensions/groovy/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js textmate/groovy.tmbundle Syntaxes/Groovy.tmLanguage ./syntaxes/groovy.tmLanguage.json" diff --git a/extensions/grunt/package.json b/extensions/grunt/package.json index dc2520b4982..f65cc6e62b0 100644 --- a/extensions/grunt/package.json +++ b/extensions/grunt/package.json @@ -5,6 +5,7 @@ "displayName": "Grunt support for VS Code", "version": "1.0.0", "icon": "images/grunt.png", + "license": "MIT", "engines": { "vscode": "*" }, @@ -19,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^8.10.25" + "@types/node": "^10.14.8" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/grunt/src/main.ts b/extensions/grunt/src/main.ts index 09a812ac06f..22b6e9e41cd 100644 --- a/extensions/grunt/src/main.ts +++ b/extensions/grunt/src/main.ts @@ -54,14 +54,14 @@ function isTestTask(name: string): boolean { let _channel: vscode.OutputChannel; function getOutputChannel(): vscode.OutputChannel { if (!_channel) { - _channel = vscode.window.createOutputChannel('Gulp Auto Detection'); + _channel = vscode.window.createOutputChannel('Grunt Auto Detection'); } return _channel; } function showError() { - vscode.window.showWarningMessage(localize('gulpTaskDetectError', 'Problem finding jake tasks. See the output for more information.'), - localize('jakeShowOutput', 'Go to output')).then(() => { + vscode.window.showWarningMessage(localize('gruntTaskDetectError', 'Problem finding grunt tasks. See the output for more information.'), + localize('gruntShowOutput', 'Go to output')).then(() => { getOutputChannel().show(true); }); } @@ -70,12 +70,27 @@ interface GruntTaskDefinition extends vscode.TaskDefinition { file?: string; } +async function findGruntCommand(rootPath: string): Promise { + let command: string; + let platform = process.platform; + if (platform === 'win32' && await exists(path.join(rootPath!, 'node_modules', '.bin', 'grunt.cmd'))) { + command = path.join('.', 'node_modules', '.bin', 'grunt.cmd'); + } else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(rootPath!, 'node_modules', '.bin', 'grunt'))) { + command = path.join('.', 'node_modules', '.bin', 'grunt'); + } else { + command = 'grunt'; + } + return command; +} + class FolderDetector { private fileWatcher: vscode.FileSystemWatcher | undefined; private promise: Thenable | undefined; - constructor(private _workspaceFolder: vscode.WorkspaceFolder) { + constructor( + private _workspaceFolder: vscode.WorkspaceFolder, + private _gruntCommand: Promise) { } public get workspaceFolder(): vscode.WorkspaceFolder { @@ -95,10 +110,28 @@ class FolderDetector { } public async getTasks(): Promise { - if (!this.promise) { - this.promise = this.computeTasks(); + if (this.isEnabled()) { + if (!this.promise) { + this.promise = this.computeTasks(); + } + return this.promise; + } else { + return []; } - return this.promise; + } + + public async getTask(_task: vscode.Task): Promise { + const gruntTask = (_task.definition).task; + if (gruntTask) { + let kind: GruntTaskDefinition = (_task.definition); + let options: vscode.ShellExecutionOptions = { cwd: this.workspaceFolder.uri.fsPath }; + let source = 'grunt'; + let task = gruntTask.indexOf(' ') === -1 + ? new vscode.Task(kind, this.workspaceFolder, gruntTask, source, new vscode.ShellExecution(`${await this._gruntCommand} ${name}`, options)) + : new vscode.Task(kind, this.workspaceFolder, gruntTask, source, new vscode.ShellExecution(`${await this._gruntCommand} "${name}"`, options)); + return task; + } + return undefined; } private async computeTasks(): Promise { @@ -111,17 +144,7 @@ class FolderDetector { return emptyTasks; } - let command: string; - let platform = process.platform; - if (platform === 'win32' && await exists(path.join(rootPath!, 'node_modules', '.bin', 'grunt.cmd'))) { - command = path.join('.', 'node_modules', '.bin', 'grunt.cmd'); - } else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(rootPath!, 'node_modules', '.bin', 'grunt'))) { - command = path.join('.', 'node_modules', '.bin', 'grunt'); - } else { - command = 'grunt'; - } - - let commandLine = `${command} --help --no-color`; + let commandLine = `${await this._gruntCommand} --help --no-color`; try { let { stdout, stderr } = await exec(commandLine, { cwd: rootPath }); if (stderr) { @@ -168,8 +191,8 @@ class FolderDetector { let source = 'grunt'; let options: vscode.ShellExecutionOptions = { cwd: this.workspaceFolder.uri.fsPath }; let task = name.indexOf(' ') === -1 - ? new vscode.Task(kind, this.workspaceFolder, name, source, new vscode.ShellExecution(`${command} ${name}`, options)) - : new vscode.Task(kind, this.workspaceFolder, name, source, new vscode.ShellExecution(`${command} "${name}"`, options)); + ? new vscode.Task(kind, this.workspaceFolder, name, source, new vscode.ShellExecution(`${await this._gruntCommand} ${name}`, options)) + : new vscode.Task(kind, this.workspaceFolder, name, source, new vscode.ShellExecution(`${await this._gruntCommand} "${name}"`, options)); result.push(task); let lowerCaseTaskName = name.toLowerCase(); if (isBuildTask(lowerCaseTaskName)) { @@ -230,7 +253,7 @@ class TaskDetector { this.detectors.clear(); } - private updateWorkspaceFolders(added: vscode.WorkspaceFolder[], removed: vscode.WorkspaceFolder[]): void { + private updateWorkspaceFolders(added: readonly vscode.WorkspaceFolder[], removed: readonly vscode.WorkspaceFolder[]): void { for (let remove of removed) { let detector = this.detectors.get(remove.uri.toString()); if (detector) { @@ -239,9 +262,9 @@ class TaskDetector { } } for (let add of added) { - let detector = new FolderDetector(add); + let detector = new FolderDetector(add, findGruntCommand(add.uri.fsPath)); + this.detectors.set(add.uri.toString(), detector); if (detector.isEnabled()) { - this.detectors.set(add.uri.toString(), detector); detector.start(); } } @@ -250,18 +273,16 @@ class TaskDetector { private updateConfiguration(): void { for (let detector of this.detectors.values()) { - if (!detector.isEnabled()) { - detector.dispose(); - this.detectors.delete(detector.workspaceFolder.uri.toString()); - } + detector.dispose(); + this.detectors.delete(detector.workspaceFolder.uri.toString()); } let folders = vscode.workspace.workspaceFolders; if (folders) { for (let folder of folders) { if (!this.detectors.has(folder.uri.toString())) { - let detector = new FolderDetector(folder); + let detector = new FolderDetector(folder, findGruntCommand(folder.uri.fsPath)); + this.detectors.set(folder.uri.toString(), detector); if (detector.isEnabled()) { - this.detectors.set(folder.uri.toString(), detector); detector.start(); } } @@ -272,12 +293,13 @@ class TaskDetector { private updateProvider(): void { if (!this.taskProvider && this.detectors.size > 0) { - this.taskProvider = vscode.workspace.registerTaskProvider('gulp', { - provideTasks: () => { - return this.getTasks(); + const thisCapture = this; + this.taskProvider = vscode.workspace.registerTaskProvider('grunt', { + provideTasks: (): Promise => { + return thisCapture.getTasks(); }, - resolveTask(_task: vscode.Task): vscode.Task | undefined { - return undefined; + resolveTask(_task: vscode.Task): Promise { + return thisCapture.getTask(_task); } }); } @@ -312,6 +334,24 @@ class TaskDetector { }); } } + + public async getTask(task: vscode.Task): Promise { + if (this.detectors.size === 0) { + return undefined; + } else if (this.detectors.size === 1) { + return this.detectors.values().next().value.getTask(task); + } else { + if ((task.scope === vscode.TaskScope.Workspace) || (task.scope === vscode.TaskScope.Global)) { + return undefined; + } else if (task.scope) { + const detector = this.detectors.get(task.scope.uri.toString()); + if (detector) { + return detector.getTask(task); + } + } + return undefined; + } + } } let detector: TaskDetector; diff --git a/extensions/grunt/yarn.lock b/extensions/grunt/yarn.lock index 5e39a356be6..e6247e29255 100644 --- a/extensions/grunt/yarn.lock +++ b/extensions/grunt/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/gulp/package.json b/extensions/gulp/package.json index 0c78e7fada0..b602bf30c7d 100644 --- a/extensions/gulp/package.json +++ b/extensions/gulp/package.json @@ -5,6 +5,7 @@ "displayName": "%displayName%", "version": "1.0.0", "icon": "images/gulp.png", + "license": "MIT", "engines": { "vscode": "*" }, @@ -19,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^8.10.25" + "@types/node": "^10.14.8" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/gulp/src/main.ts b/extensions/gulp/src/main.ts index 1b89a4bdb1a..6f9a9e49334 100644 --- a/extensions/gulp/src/main.ts +++ b/extensions/gulp/src/main.ts @@ -67,6 +67,24 @@ function showError() { }); } +async function findGulpCommand(rootPath: string): Promise { + let gulpCommand: string; + let platform = process.platform; + if (platform === 'win32' && await exists(path.join(rootPath, 'node_modules', '.bin', 'gulp.cmd'))) { + const globalGulp = path.join(process.env.APPDATA ? process.env.APPDATA : '', 'npm', 'gulp.cmd'); + if (await exists(globalGulp)) { + gulpCommand = '"' + globalGulp + '"'; + } else { + gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp.cmd'); + } + } else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(rootPath, 'node_modules', '.bin', 'gulp'))) { + gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp'); + } else { + gulpCommand = 'gulp'; + } + return gulpCommand; +} + interface GulpTaskDefinition extends vscode.TaskDefinition { task: string; file?: string; @@ -77,7 +95,9 @@ class FolderDetector { private fileWatcher: vscode.FileSystemWatcher | undefined; private promise: Thenable | undefined; - constructor(private _workspaceFolder: vscode.WorkspaceFolder) { + constructor( + private _workspaceFolder: vscode.WorkspaceFolder, + private _gulpCommand: Promise) { } public get workspaceFolder(): vscode.WorkspaceFolder { @@ -97,10 +117,25 @@ class FolderDetector { } public async getTasks(): Promise { - if (!this.promise) { - this.promise = this.computeTasks(); + if (this.isEnabled()) { + if (!this.promise) { + this.promise = this.computeTasks(); + } + return this.promise; + } else { + return []; } - return this.promise; + } + + public async getTask(_task: vscode.Task): Promise { + const gulpTask = (_task.definition).task; + if (gulpTask) { + let kind: GulpTaskDefinition = (_task.definition); + let options: vscode.ShellExecutionOptions = { cwd: this.workspaceFolder.uri.fsPath }; + let task = new vscode.Task(kind, this.workspaceFolder, gulpTask, 'gulp', new vscode.ShellExecution(await this._gulpCommand, [gulpTask], options)); + return task; + } + return undefined; } private async computeTasks(): Promise { @@ -117,22 +152,7 @@ class FolderDetector { } } - let gulpCommand: string; - let platform = process.platform; - if (platform === 'win32' && await exists(path.join(rootPath!, 'node_modules', '.bin', 'gulp.cmd'))) { - const globalGulp = path.join(process.env.APPDATA ? process.env.APPDATA : '', 'npm', 'gulp.cmd'); - if (await exists(globalGulp)) { - gulpCommand = globalGulp; - } else { - gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp.cmd'); - } - } else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(rootPath!, 'node_modules', '.bin', 'gulp'))) { - gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp'); - } else { - gulpCommand = 'gulp'; - } - - let commandLine = `${gulpCommand} --tasks-simple --no-color`; + let commandLine = `${await this._gulpCommand} --tasks-simple --no-color`; try { let { stdout, stderr } = await exec(commandLine, { cwd: rootPath }); if (stderr && stderr.length > 0) { @@ -151,7 +171,7 @@ class FolderDetector { task: line }; let options: vscode.ShellExecutionOptions = { cwd: this.workspaceFolder.uri.fsPath }; - let task = new vscode.Task(kind, this.workspaceFolder, line, 'gulp', new vscode.ShellExecution(`${gulpCommand} ${line}`, options)); + let task = new vscode.Task(kind, this.workspaceFolder, line, 'gulp', new vscode.ShellExecution(await this._gulpCommand, [line], options)); result.push(task); let lowerCaseLine = line.toLowerCase(); if (isBuildTask(lowerCaseLine)) { @@ -209,7 +229,7 @@ class TaskDetector { this.detectors.clear(); } - private updateWorkspaceFolders(added: vscode.WorkspaceFolder[], removed: vscode.WorkspaceFolder[]): void { + private updateWorkspaceFolders(added: readonly vscode.WorkspaceFolder[], removed: readonly vscode.WorkspaceFolder[]): void { for (let remove of removed) { let detector = this.detectors.get(remove.uri.toString()); if (detector) { @@ -218,9 +238,9 @@ class TaskDetector { } } for (let add of added) { - let detector = new FolderDetector(add); + let detector = new FolderDetector(add, findGulpCommand(add.uri.fsPath)); + this.detectors.set(add.uri.toString(), detector); if (detector.isEnabled()) { - this.detectors.set(add.uri.toString(), detector); detector.start(); } } @@ -229,18 +249,16 @@ class TaskDetector { private updateConfiguration(): void { for (let detector of this.detectors.values()) { - if (!detector.isEnabled()) { - detector.dispose(); - this.detectors.delete(detector.workspaceFolder.uri.toString()); - } + detector.dispose(); + this.detectors.delete(detector.workspaceFolder.uri.toString()); } let folders = vscode.workspace.workspaceFolders; if (folders) { for (let folder of folders) { if (!this.detectors.has(folder.uri.toString())) { - let detector = new FolderDetector(folder); + let detector = new FolderDetector(folder, findGulpCommand(folder.uri.fsPath)); + this.detectors.set(folder.uri.toString(), detector); if (detector.isEnabled()) { - this.detectors.set(folder.uri.toString(), detector); detector.start(); } } @@ -251,12 +269,13 @@ class TaskDetector { private updateProvider(): void { if (!this.taskProvider && this.detectors.size > 0) { + const thisCapture = this; this.taskProvider = vscode.workspace.registerTaskProvider('gulp', { - provideTasks: () => { - return this.getTasks(); + provideTasks(): Promise { + return thisCapture.getTasks(); }, - resolveTask(_task: vscode.Task): vscode.Task | undefined { - return undefined; + resolveTask(_task: vscode.Task): Promise { + return thisCapture.getTask(_task); } }); } @@ -291,6 +310,25 @@ class TaskDetector { }); } } + + public async getTask(task: vscode.Task): Promise { + if (this.detectors.size === 0) { + return undefined; + } else if (this.detectors.size === 1) { + return this.detectors.values().next().value.getTask(task); + } else { + if ((task.scope === vscode.TaskScope.Workspace) || (task.scope === vscode.TaskScope.Global)) { + // Not supported, we don't have enough info to create the task. + return undefined; + } else if (task.scope) { + const detector = this.detectors.get(task.scope.uri.toString()); + if (detector) { + return detector.getTask(task); + } + } + return undefined; + } + } } let detector: TaskDetector; @@ -301,4 +339,4 @@ export function activate(_context: vscode.ExtensionContext): void { export function deactivate(): void { detector.dispose(); -} \ No newline at end of file +} diff --git a/extensions/gulp/yarn.lock b/extensions/gulp/yarn.lock index 5e39a356be6..e6247e29255 100644 --- a/extensions/gulp/yarn.lock +++ b/extensions/gulp/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/handlebars/cgmanifest.json b/extensions/handlebars/cgmanifest.json index 4d30387e915..39f8efc676d 100644 --- a/extensions/handlebars/cgmanifest.json +++ b/extensions/handlebars/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "daaain/Handlebars", "repositoryUrl": "https://github.com/daaain/Handlebars", - "commitHash": "790f2b0222098a3a236bd9e91bb9a039eeca4d8e" + "commitHash": "85a153a6f759df4e8da7533e1b3651f007867c51" } }, "licenseDetail": [ @@ -29,7 +29,7 @@ "THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." ], "license": "MIT", - "version": "1.7.1" + "version": "1.8.0" } ], "version": 1 diff --git a/extensions/handlebars/language-configuration.json b/extensions/handlebars/language-configuration.json index ab66bc5961a..cb2de742fb0 100644 --- a/extensions/handlebars/language-configuration.json +++ b/extensions/handlebars/language-configuration.json @@ -6,6 +6,7 @@ [""], ["<", ">"], ["{{", "}}"], + ["{{{", "}}}"], ["{", "}"], ["(", ")"] ], @@ -19,6 +20,7 @@ "surroundingPairs": [ { "open": "'", "close": "'" }, { "open": "\"", "close": "\"" }, - { "open": "<", "close": ">" } + { "open": "<", "close": ">" }, + { "open": "{", "close": "}" } ] } diff --git a/extensions/handlebars/package.json b/extensions/handlebars/package.json index fdb8d4fc734..37b63ee54ce 100644 --- a/extensions/handlebars/package.json +++ b/extensions/handlebars/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "0.10.x" }, diff --git a/extensions/handlebars/syntaxes/Handlebars.tmLanguage.json b/extensions/handlebars/syntaxes/Handlebars.tmLanguage.json index 957f16ae035..be8b06fa085 100644 --- a/extensions/handlebars/syntaxes/Handlebars.tmLanguage.json +++ b/extensions/handlebars/syntaxes/Handlebars.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/daaain/Handlebars/commit/790f2b0222098a3a236bd9e91bb9a039eeca4d8e", + "version": "https://github.com/daaain/Handlebars/commit/85a153a6f759df4e8da7533e1b3651f007867c51", "name": "Handlebars", "scopeName": "text.html.handlebars", "patterns": [ @@ -653,7 +653,7 @@ ] }, "else_token": { - "begin": "(\\{\\{)(~?else)(@?\\s(if)\\s([-a-zA-Z0-9_\\./]+))?", + "begin": "(\\{\\{)(~?else)(@?\\s(if)\\s([-a-zA-Z0-9_\\.\\(\\s\\)/]+))?", "end": "(~?\\}\\}\\}*)", "name": "meta.function.inline.else.handlebars", "beginCaptures": { diff --git a/extensions/hlsl/cgmanifest.json b/extensions/hlsl/cgmanifest.json index 92137372cc0..44b3a016ee0 100644 --- a/extensions/hlsl/cgmanifest.json +++ b/extensions/hlsl/cgmanifest.json @@ -14,4 +14,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/hlsl/package.json b/extensions/hlsl/package.json index f68ce50ee72..b2f635b4aa0 100644 --- a/extensions/hlsl/package.json +++ b/extensions/hlsl/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js tgjones/shaders-tmLanguage grammars/hlsl.json ./syntaxes/hlsl.tmLanguage.json" diff --git a/extensions/html-language-features/.vscode/launch.json b/extensions/html-language-features/.vscode/launch.json index 28ec3d3dc89..032dc46bb43 100644 --- a/extensions/html-language-features/.vscode/launch.json +++ b/extensions/html-language-features/.vscode/launch.json @@ -17,8 +17,7 @@ ], "stopOnEntry": false, "sourceMaps": true, - "outFiles": ["${workspaceFolder}/client/out/**/*.js"], - "preLaunchTask": "npm" + "outFiles": ["${workspaceFolder}/client/out/**/*.js"] }, { "name": "Launch Tests", @@ -28,8 +27,7 @@ "args": ["--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/client/out/test" ], "stopOnEntry": false, "sourceMaps": true, - "outFiles": ["${workspaceFolder}/client/out/test/**/*.js"], - "preLaunchTask": "npm" + "outFiles": ["${workspaceFolder}/client/out/test/**/*.js"] }, { "name": "Attach Language Server", diff --git a/extensions/html-language-features/.vscode/settings.json b/extensions/html-language-features/.vscode/settings.json index e46111f13be..569ac10cf8f 100644 --- a/extensions/html-language-features/.vscode/settings.json +++ b/extensions/html-language-features/.vscode/settings.json @@ -1,3 +1,6 @@ { - "editor.insertSpaces": false + "editor.insertSpaces": false, + "prettier.semi": true, + "prettier.singleQuote": true, + "prettier.printWidth": 120, } \ No newline at end of file diff --git a/extensions/html-language-features/client/src/customData.ts b/extensions/html-language-features/client/src/customData.ts new file mode 100644 index 00000000000..d716c0ae347 --- /dev/null +++ b/extensions/html-language-features/client/src/customData.ts @@ -0,0 +1,66 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from 'path'; +import { workspace, WorkspaceFolder, extensions } from 'vscode'; + +interface ExperimentalConfig { + experimental?: { + customData?: string[]; + }; +} + +export function getCustomDataPathsInAllWorkspaces(workspaceFolders: WorkspaceFolder[] | undefined): string[] { + const dataPaths: string[] = []; + + if (!workspaceFolders) { + return dataPaths; + } + + workspaceFolders.forEach(wf => { + const allHtmlConfig = workspace.getConfiguration(undefined, wf.uri); + const wfHtmlConfig = allHtmlConfig.inspect('html'); + + if ( + wfHtmlConfig && + wfHtmlConfig.workspaceFolderValue && + wfHtmlConfig.workspaceFolderValue.experimental && + wfHtmlConfig.workspaceFolderValue.experimental.customData + ) { + const customData = wfHtmlConfig.workspaceFolderValue.experimental.customData; + if (Array.isArray(customData)) { + customData.forEach(t => { + if (typeof t === 'string') { + dataPaths.push(path.resolve(wf.uri.fsPath, t)); + } + }); + } + } + }); + + return dataPaths; +} + +export function getCustomDataPathsFromAllExtensions(): string[] { + const dataPaths: string[] = []; + + for (const extension of extensions.all) { + const contributes = extension.packageJSON && extension.packageJSON.contributes; + + if ( + contributes && + contributes.html && + contributes.html.experimental.customData && + Array.isArray(contributes.html.experimental.customData) + ) { + const relativePaths: string[] = contributes.html.experimental.customData; + relativePaths.forEach(rp => { + dataPaths.push(path.resolve(extension.extensionPath, rp)); + }); + } + } + + return dataPaths; +} diff --git a/extensions/html-language-features/client/src/htmlMain.ts b/extensions/html-language-features/client/src/htmlMain.ts index 0b84091bed7..5f98f732b52 100644 --- a/extensions/html-language-features/client/src/htmlMain.ts +++ b/extensions/html-language-features/client/src/htmlMain.ts @@ -13,6 +13,7 @@ import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, Re import { EMPTY_ELEMENTS } from './htmlEmptyTagsShared'; import { activateTagClosing } from './tagClosing'; import TelemetryReporter from 'vscode-extension-telemetry'; +import { getCustomDataPathsInAllWorkspaces, getCustomDataPathsFromAllExtensions } from './customData'; namespace TagCloseRequest { export const type: RequestType = new RequestType('html/tag'); @@ -46,26 +47,13 @@ export function activate(context: ExtensionContext) { debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } }; - let documentSelector = ['html', 'handlebars', 'razor']; + let documentSelector = ['html', 'handlebars']; let embeddedLanguages = { css: true, javascript: true }; - let tagPaths: string[] = workspace.getConfiguration('html').get('experimental.custom.tags', []); - let attributePaths: string[] = workspace.getConfiguration('html').get('experimental.custom.attributes', []); - - if (tagPaths && tagPaths.length > 0) { - if (!workspace.workspaceFolders) { - tagPaths = []; - } else { - try { - const workspaceRoot = workspace.workspaceFolders[0].uri.fsPath; - tagPaths = tagPaths.map(d => { - return path.resolve(workspaceRoot, d); - }); - } catch (err) { - tagPaths = []; - } - } - } + let dataPaths = [ + ...getCustomDataPathsInAllWorkspaces(workspace.workspaceFolders), + ...getCustomDataPathsFromAllExtensions() + ]; // Options to control the language client let clientOptions: LanguageClientOptions = { @@ -75,8 +63,7 @@ export function activate(context: ExtensionContext) { }, initializationOptions: { embeddedLanguages, - tagPaths, - attributePaths + dataPaths } }; @@ -91,7 +78,7 @@ export function activate(context: ExtensionContext) { let param = client.code2ProtocolConverter.asTextDocumentPositionParams(document, position); return client.sendRequest(TagCloseRequest.type, param); }; - disposable = activateTagClosing(tagRequestor, { html: true, handlebars: true, razor: true }, 'html.autoClosingTags'); + disposable = activateTagClosing(tagRequestor, { html: true, handlebars: true }, 'html.autoClosingTags'); toDispose.push(disposable); disposable = client.onTelemetry(e => { @@ -136,24 +123,11 @@ export function activate(context: ExtensionContext) { ], }); - languages.setLanguageConfiguration('razor', { - wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g, - onEnterRules: [ - { - beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), - afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>/i, - action: { indentAction: IndentAction.IndentOutdent } - }, - { - beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), - action: { indentAction: IndentAction.Indent } - } - ], - }); - const regionCompletionRegExpr = /^(\s*)(<(!(-(-\s*(#\w*)?)?)?)?)?$/; + const htmlSnippetCompletionRegExpr = /^(\s*)(<(h(t(m(l)?)?)?)?)?$/; languages.registerCompletionItemProvider(documentSelector, { provideCompletionItems(doc, pos) { + const results: CompletionItem[] = []; let lineUntilPos = doc.getText(new Range(new Position(pos.line, 0), pos)); let match = lineUntilPos.match(regionCompletionRegExpr); if (match) { @@ -164,15 +138,41 @@ export function activate(context: ExtensionContext) { beginProposal.documentation = localize('folding.start', 'Folding Region Start'); beginProposal.filterText = match[2]; beginProposal.sortText = 'za'; + results.push(beginProposal); let endProposal = new CompletionItem('#endregion', CompletionItemKind.Snippet); endProposal.range = range; endProposal.insertText = new SnippetString(''); endProposal.documentation = localize('folding.end', 'Folding Region End'); endProposal.filterText = match[2]; endProposal.sortText = 'zb'; - return [beginProposal, endProposal]; + results.push(endProposal); } - return null; + let match2 = lineUntilPos.match(htmlSnippetCompletionRegExpr); + if (match2 && doc.getText(new Range(new Position(0, 0), pos)).match(htmlSnippetCompletionRegExpr)) { + let range = new Range(new Position(pos.line, match2[1].length), pos); + let snippetProposal = new CompletionItem('HTML sample', CompletionItemKind.Snippet); + snippetProposal.range = range; + const content = ['', + '', + '', + '\t', + '\t', + '\t${1:Page Title}', + '\t', + '\t', + '\t', + '', + '', + '\t$0', + '', + ''].join('\n'); + snippetProposal.insertText = new SnippetString(content); + snippetProposal.documentation = localize('folding.html', 'Simple HTML5 starting point'); + snippetProposal.filterText = match2[2]; + snippetProposal.sortText = 'za'; + results.push(snippetProposal); + } + return results; } }); } @@ -201,4 +201,4 @@ function readJSONFile(location: string) { export function deactivate(): Promise { return telemetryReporter ? telemetryReporter.dispose() : Promise.resolve(null); -} \ No newline at end of file +} diff --git a/extensions/html-language-features/client/src/tagClosing.ts b/extensions/html-language-features/client/src/tagClosing.ts index 35511e63f43..298edcdaa0a 100644 --- a/extensions/html-language-features/client/src/tagClosing.ts +++ b/extensions/html-language-features/client/src/tagClosing.ts @@ -32,7 +32,7 @@ export function activateTagClosing(tagProvider: (document: TextDocument, positio isEnabled = true; } - function onDidChangeTextDocument(document: TextDocument, changes: TextDocumentContentChangeEvent[]) { + function onDidChangeTextDocument(document: TextDocument, changes: readonly TextDocumentContentChangeEvent[]) { if (!isEnabled) { return; } diff --git a/extensions/html-language-features/client/src/typings/ref.d.ts b/extensions/html-language-features/client/src/typings/ref.d.ts index 9c1a5df18ed..be1d1b0b776 100644 --- a/extensions/html-language-features/client/src/typings/ref.d.ts +++ b/extensions/html-language-features/client/src/typings/ref.d.ts @@ -4,3 +4,4 @@ *--------------------------------------------------------------------------------------------*/ /// +/// diff --git a/extensions/html-language-features/package.json b/extensions/html-language-features/package.json index 78236179394..3985c07b972 100644 --- a/extensions/html-language-features/package.json +++ b/extensions/html-language-features/package.json @@ -1,9 +1,11 @@ { + "enableProposedApi": true, "name": "html-language-features", "displayName": "%displayName%", "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217", "engines": { "vscode": "0.10.x" @@ -11,8 +13,7 @@ "icon": "icons/html.png", "activationEvents": [ "onLanguage:html", - "onLanguage:handlebars", - "onLanguage:razor" + "onLanguage:handlebars" ], "main": "./client/out/htmlMain", "scripts": { @@ -31,13 +32,14 @@ "type": "object", "title": "HTML", "properties": { - "html.experimental.custom.tags": { + "html.experimental.customData": { "type": "array", - "description": "A list of JSON file paths that define custom tags." - }, - "html.experimental.custom.attributes": { - "type": "array", - "description": "A list of JSON file paths that define custom attributes." + "description": "A list of JSON file paths that define custom tags, properties and other HTML syntax constructs. Only workspace folder setting will be read.", + "default": [], + "items": { + "type": "string" + }, + "scope": "resource" }, "html.format.enable": { "type": "boolean", @@ -120,31 +122,21 @@ "force", "force-aligned", "force-expand-multiline", - "aligned-multiple" + "aligned-multiple", + "preserve", + "preserve-aligned" ], "enumDescriptions": [ "%html.format.wrapAttributes.auto%", "%html.format.wrapAttributes.force%", "%html.format.wrapAttributes.forcealign%", "%html.format.wrapAttributes.forcemultiline%", - "%html.format.wrapAttributes.alignedmultiple%" + "%html.format.wrapAttributes.alignedmultiple%", + "%html.format.wrapAttributes.preserve%", + "%html.format.wrapAttributes.preservealigned%" ], "description": "%html.format.wrapAttributes.desc%" }, - "html.suggest.angular1": { - "deprecationMessage": "Angular 1 is obsolete and Angular completion will be removed.", - "type": "boolean", - "scope": "resource", - "default": false, - "description": "%html.suggest.angular1.desc%" - }, - "html.suggest.ionic": { - "deprecationMessage": "Ionic 1 is obsolete and Ionic completion will be removed.", - "type": "boolean", - "scope": "resource", - "default": false, - "description": "%html.suggest.ionic.desc%" - }, "html.suggest.html5": { "type": "boolean", "scope": "resource", @@ -181,14 +173,20 @@ "description": "%html.trace.server.desc%" } } - } + }, + "jsonValidation": [ + { + "fileMatch": "*.html-data.json", + "url": "https://raw.githubusercontent.com/Microsoft/vscode-html-languageservice/master/docs/customData.schema.json" + } + ] }, "dependencies": { - "vscode-extension-telemetry": "0.1.0", - "vscode-languageclient": "^5.1.0", - "vscode-nls": "^4.0.0" + "vscode-extension-telemetry": "0.1.1", + "vscode-languageclient": "^5.3.0-next.6", + "vscode-nls": "^4.1.1" }, "devDependencies": { - "@types/node": "^8.10.25" + "@types/node": "^10.14.8" } } diff --git a/extensions/html-language-features/package.nls.json b/extensions/html-language-features/package.nls.json index c6923ce881e..6a436fa5cb3 100644 --- a/extensions/html-language-features/package.nls.json +++ b/extensions/html-language-features/package.nls.json @@ -1,6 +1,6 @@ { "displayName": "HTML Language Features", - "description": "Provides rich language support for HTML, Razor, and Handlebar files", + "description": "Provides rich language support for HTML and Handlebar files", "html.format.enable.desc": "Enable/disable default HTML formatter.", "html.format.wrapLineLength.desc": "Maximum amount of characters per line (0 = disable).", "html.format.unformatted.desc": "List of tags, comma separated, that shouldn't be reformatted. `null` defaults to all tags listed at https://www.w3.org/TR/html5/dom.html#phrasing-content.", @@ -17,8 +17,8 @@ "html.format.wrapAttributes.forcealign": "Wrap each attribute except first and keep aligned.", "html.format.wrapAttributes.forcemultiline": "Wrap each attribute.", "html.format.wrapAttributes.alignedmultiple": "Wrap when line length is exceeded, align attributes vertically.", - "html.suggest.angular1.desc": "Controls whether the built-in HTML language support suggests Angular V1 tags and properties.", - "html.suggest.ionic.desc": "Controls whether the built-in HTML language support suggests Ionic tags, properties and values.", + "html.format.wrapAttributes.preserve": "Preserve wrapping of attributes", + "html.format.wrapAttributes.preservealigned": "Preserve wrapping of attributes but align.", "html.suggest.html5.desc": "Controls whether the built-in HTML language support suggests HTML5 tags, properties and values.", "html.trace.server.desc": "Traces the communication between VS Code and the HTML language server.", "html.validate.scripts": "Controls whether the built-in HTML language support validates embedded scripts.", diff --git a/extensions/html-language-features/server/extension.webpack.config.js b/extensions/html-language-features/server/extension.webpack.config.js index a535ddeae9a..77b86e718b1 100644 --- a/extensions/html-language-features/server/extension.webpack.config.js +++ b/extensions/html-language-features/server/extension.webpack.config.js @@ -9,7 +9,6 @@ const withDefaults = require('../../shared.webpack.config'); const path = require('path'); -var webpack = require('webpack'); module.exports = withDefaults({ context: path.join(__dirname), @@ -22,12 +21,5 @@ module.exports = withDefaults({ }, externals: { 'typescript': 'commonjs typescript' - }, - plugins: [ - new webpack.NormalModuleReplacementPlugin( - /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, - require.resolve('./build/filesFillIn') - ), - new webpack.IgnorePlugin(/vertx/) - ], + } }); diff --git a/extensions/html-language-features/server/package.json b/extensions/html-language-features/server/package.json index 14eb36c4dd9..95a97f1110f 100644 --- a/extensions/html-language-features/server/package.json +++ b/extensions/html-language-features/server/package.json @@ -9,16 +9,16 @@ }, "main": "./out/htmlServerMain", "dependencies": { - "vscode-css-languageservice": "^3.0.13-next.3", - "vscode-html-languageservice": "^2.1.11-next.2", - "vscode-languageserver": "^5.1.0", - "vscode-languageserver-types": "^3.13.0", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.6" + "vscode-css-languageservice": "^4.0.3-next.1", + "vscode-html-languageservice": "^3.0.4-next.0", + "vscode-languageserver": "^5.3.0-next.8", + "vscode-languageserver-types": "3.15.0-next.2", + "vscode-nls": "^4.1.1", + "vscode-uri": "^2.0.3" }, "devDependencies": { "@types/mocha": "2.2.33", - "@types/node": "^8.10.25", + "@types/node": "^10.14.8", "glob": "^7.1.2", "mocha": "^5.2.0", "mocha-junit-reporter": "^1.17.0", diff --git a/extensions/html-language-features/server/src/customData.ts b/extensions/html-language-features/server/src/customData.ts new file mode 100644 index 00000000000..1d550eddf9f --- /dev/null +++ b/extensions/html-language-features/server/src/customData.ts @@ -0,0 +1,29 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IHTMLDataProvider, newHTMLDataProvider } from 'vscode-html-languageservice'; +import * as fs from 'fs'; + +export function getDataProviders(dataPaths?: string[]): IHTMLDataProvider[] { + if (!dataPaths) { + return []; + } + + const providers: IHTMLDataProvider[] = []; + + dataPaths.forEach((path, i) => { + try { + if (fs.existsSync(path)) { + const htmlData = JSON.parse(fs.readFileSync(path, 'utf-8')); + + providers.push(newHTMLDataProvider(`customProvider${i}`, htmlData)); + } + } catch (err) { + console.log(`Failed to load tag from ${path}`); + } + }); + + return providers; +} \ No newline at end of file diff --git a/extensions/html-language-features/server/src/htmlServerMain.ts b/extensions/html-language-features/server/src/htmlServerMain.ts index 1b32205c2e3..01b43d9a9ba 100644 --- a/extensions/html-language-features/server/src/htmlServerMain.ts +++ b/extensions/html-language-features/server/src/htmlServerMain.ts @@ -11,17 +11,15 @@ import { } from 'vscode-languageserver'; import { TextDocument, Diagnostic, DocumentLink, SymbolInformation } from 'vscode-languageserver-types'; import { getLanguageModes, LanguageModes, Settings } from './modes/languageModes'; -import * as fs from 'fs'; import { format } from './modes/formatting'; import { pushAll } from './utils/arrays'; import { getDocumentContext } from './utils/documentContext'; -import uri from 'vscode-uri'; +import { URI } from 'vscode-uri'; import { formatError, runSafe, runSafeAsync } from './utils/runner'; import { getFoldingRanges } from './modes/htmlFolding'; -import { parseTagSet, parseAttributes } from './utils/tagDefinitions'; -import { ITagSet, IAttributeSet } from 'vscode-html-languageservice'; +import { getDataProviders } from './customData'; namespace TagCloseRequest { export const type: RequestType = new RequestType('html/tag'); @@ -40,8 +38,7 @@ process.on('uncaughtException', (e: any) => { console.error(formatError(`Unhandled exception`, e)); }); -// Create a simple text document manager. The text document manager -// supports full document sync only +// Create a text document manager. const documents: TextDocuments = new TextDocuments(); // Make the text document manager listen on the connection // for open, change and close text document events @@ -87,50 +84,19 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { if (!Array.isArray(workspaceFolders)) { workspaceFolders = []; if (params.rootPath) { - workspaceFolders.push({ name: '', uri: uri.file(params.rootPath).toString() }); + workspaceFolders.push({ name: '', uri: URI.file(params.rootPath).toString() }); } } - const tagPaths: string[] = params.initializationOptions.tagPaths; - const attributePaths: string[] = params.initializationOptions.attributePaths; - const htmlTags: ITagSet = {}; - const htmlAttributes: IAttributeSet = {}; - - if (tagPaths) { - tagPaths.forEach(path => { - try { - if (fs.existsSync(path)) { - const tagSet = parseTagSet(fs.readFileSync(path, 'utf-8')); - for (let tag in tagSet) { - htmlTags[tag] = tagSet[tag]; - } - } - } catch (err) { - console.log(`Failed to laod tag from ${path}`); - } - }); - } - if (htmlAttributes) { - attributePaths.forEach(path => { - try { - if (fs.existsSync(path)) { - const attributeSet = parseAttributes(fs.readFileSync(path, 'utf-8')); - for (let ga in attributeSet) { - htmlAttributes[ga] = attributeSet[ga]; - } - } - } catch (err) { - console.log(`Failed to load attributes from ${path}`); - } - }); - } + const dataPaths: string[] = params.initializationOptions.dataPaths; + const providers = getDataProviders(dataPaths); const workspace = { get settings() { return globalSettings; }, get folders() { return workspaceFolders; } }; - languageModes = getLanguageModes(initializationOptions ? initializationOptions.embeddedLanguages : { css: true, javascript: true }, workspace, htmlTags, htmlAttributes); + languageModes = getLanguageModes(initializationOptions ? initializationOptions.embeddedLanguages : { css: true, javascript: true }, workspace, params.capabilities, providers); documents.onDidClose(e => { languageModes.onDocumentRemoved(e.document); @@ -169,7 +135,8 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { signatureHelpProvider: { triggerCharacters: ['('] }, referencesProvider: true, colorProvider: {}, - foldingRangeProvider: true + foldingRangeProvider: true, + selectionRangeProvider: true }; return { capabilities }; }); @@ -208,7 +175,7 @@ connection.onDidChangeConfiguration((change) => { const enableFormatter = globalSettings && globalSettings.html && globalSettings.html.format && globalSettings.html.format.enable; if (enableFormatter) { if (!formatterRegistration) { - const documentSelector: DocumentSelector = [{ language: 'html' }, { language: 'handlebars' }]; // don't register razor, the formatter does more harm than good + const documentSelector: DocumentSelector = [{ language: 'html' }, { language: 'handlebars' }]; formatterRegistration = connection.client.register(DocumentRangeFormattingRequest.type, { documentSelector }); } } else if (formatterRegistration) { @@ -488,6 +455,21 @@ connection.onFoldingRanges((params, token) => { }, null, `Error while computing folding regions for ${params.textDocument.uri}`, token); }); +connection.onSelectionRanges((params, token) => { + return runSafe(() => { + const document = documents.get(params.textDocument.uri); + const positions: Position[] = params.positions; + + if (document) { + const htmlMode = languageModes.getMode('html'); + if (htmlMode && htmlMode.getSelectionRanges) { + return htmlMode.getSelectionRanges(document, positions); + } + } + return []; + }, [], `Error while computing selection ranges for ${params.textDocument.uri}`, token); +}); + // Listen on the connection connection.listen(); \ No newline at end of file diff --git a/extensions/html-language-features/server/src/modes/cssMode.ts b/extensions/html-language-features/server/src/modes/cssMode.ts index 168c7ceffa0..6e60c32d87c 100644 --- a/extensions/html-language-features/server/src/modes/cssMode.ts +++ b/extensions/html-language-features/server/src/modes/cssMode.ts @@ -5,13 +5,12 @@ import { LanguageModelCache, getLanguageModelCache } from '../languageModelCache'; import { TextDocument, Position, Range, CompletionList } from 'vscode-languageserver-types'; -import { getCSSLanguageService, Stylesheet, FoldingRange } from 'vscode-css-languageservice'; +import { Stylesheet, FoldingRange, LanguageService as CSSLanguageService } from 'vscode-css-languageservice'; import { LanguageMode, Workspace } from './languageModes'; import { HTMLDocumentRegions, CSS_STYLE_RULE } from './embeddedSupport'; import { Color } from 'vscode-languageserver'; -export function getCSSMode(documentRegions: LanguageModelCache, workspace: Workspace): LanguageMode { - let cssLanguageService = getCSSLanguageService(); +export function getCSSMode(cssLanguageService: CSSLanguageService, documentRegions: LanguageModelCache, workspace: Workspace): LanguageMode { let embeddedCSSDocuments = getLanguageModelCache(10, 60, document => documentRegions.get(document).getEmbeddedDocument('css')); let cssStylesheets = getLanguageModelCache(10, 60, document => cssLanguageService.parseStylesheet(document)); diff --git a/extensions/html-language-features/server/src/modes/htmlMode.ts b/extensions/html-language-features/server/src/modes/htmlMode.ts index 65756c5ee14..57249a65b8a 100644 --- a/extensions/html-language-features/server/src/modes/htmlMode.ts +++ b/extensions/html-language-features/server/src/modes/htmlMode.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { getLanguageModelCache } from '../languageModelCache'; -import { LanguageService as HTMLLanguageService, HTMLDocument, DocumentContext, FormattingOptions, HTMLFormatConfiguration } from 'vscode-html-languageservice'; +import { LanguageService as HTMLLanguageService, HTMLDocument, DocumentContext, FormattingOptions, HTMLFormatConfiguration, SelectionRange } from 'vscode-html-languageservice'; import { TextDocument, Position, Range, CompletionItem, FoldingRange } from 'vscode-languageserver-types'; import { LanguageMode, Workspace } from './languageModes'; import { getPathCompletionParticipant } from './pathCompletion'; @@ -15,6 +15,9 @@ export function getHTMLMode(htmlLanguageService: HTMLLanguageService, workspace: getId() { return 'html'; }, + getSelectionRanges(document: TextDocument, positions: Position[]): SelectionRange[] { + return htmlLanguageService.getSelectionRanges(document, positions); + }, doComplete(document: TextDocument, position: Position, settings = workspace.settings) { let options = settings && settings.html && settings.html.suggest; let doAutoComplete = settings && settings.html && settings.html.autoClosingTags; diff --git a/extensions/html-language-features/server/src/modes/javascriptMode.ts b/extensions/html-language-features/server/src/modes/javascriptMode.ts index c4d46d3eb24..fb1f1a9d758 100644 --- a/extensions/html-language-features/server/src/modes/javascriptMode.ts +++ b/extensions/html-language-features/server/src/modes/javascriptMode.ts @@ -173,16 +173,17 @@ export function getJavaScriptMode(documentRegions: LanguageModelCache { - return { - range: convertRange(currentTextDocument, entry.textSpan), - kind: (entry.isWriteAccess ? DocumentHighlightKind.Write : DocumentHighlightKind.Text) - }; - }); + const highlights = jsLanguageService.getDocumentHighlights(FILE_NAME, currentTextDocument.offsetAt(position), [FILE_NAME]); + const out: DocumentHighlight[] = []; + for (const entry of highlights || []) { + for (const highlight of entry.highlightSpans) { + out.push({ + range: convertRange(currentTextDocument, highlight.textSpan), + kind: highlight.kind === 'writtenReference' ? DocumentHighlightKind.Write : DocumentHighlightKind.Text + }); + } } - return []; + return out; }, findDocumentSymbols(document: TextDocument): SymbolInformation[] { updateCurrentTextDocument(document); diff --git a/extensions/html-language-features/server/src/modes/languageModes.ts b/extensions/html-language-features/server/src/modes/languageModes.ts index 28b90a4cd0c..d07e0bd80f6 100644 --- a/extensions/html-language-features/server/src/modes/languageModes.ts +++ b/extensions/html-language-features/server/src/modes/languageModes.ts @@ -3,18 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { getLanguageService as getHTMLLanguageService, DocumentContext, ITagSet, IAttributeSet } from 'vscode-html-languageservice'; -import { - CompletionItem, Location, SignatureHelp, Definition, TextEdit, TextDocument, Diagnostic, DocumentLink, Range, - Hover, DocumentHighlight, CompletionList, Position, FormattingOptions, SymbolInformation, FoldingRange -} from 'vscode-languageserver-types'; -import { ColorInformation, ColorPresentation, Color, WorkspaceFolder } from 'vscode-languageserver'; - +import { getCSSLanguageService } from 'vscode-css-languageservice'; +import { ClientCapabilities, DocumentContext, getLanguageService as getHTMLLanguageService, IHTMLDataProvider, SelectionRange } from 'vscode-html-languageservice'; +import { Color, ColorInformation, ColorPresentation, WorkspaceFolder } from 'vscode-languageserver'; +import { CompletionItem, CompletionList, Definition, Diagnostic, DocumentHighlight, DocumentLink, FoldingRange, FormattingOptions, Hover, Location, Position, Range, SignatureHelp, SymbolInformation, TextDocument, TextEdit } from 'vscode-languageserver-types'; import { getLanguageModelCache, LanguageModelCache } from '../languageModelCache'; -import { getDocumentRegions, HTMLDocumentRegions } from './embeddedSupport'; import { getCSSMode } from './cssMode'; -import { getJavaScriptMode } from './javascriptMode'; +import { getDocumentRegions, HTMLDocumentRegions } from './embeddedSupport'; import { getHTMLMode } from './htmlMode'; +import { getJavaScriptMode } from './javascriptMode'; export { ColorInformation, ColorPresentation, Color }; @@ -31,6 +28,7 @@ export interface Workspace { export interface LanguageMode { getId(): string; + getSelectionRanges?: (document: TextDocument, positions: Position[]) => SelectionRange[]; doValidation?: (document: TextDocument, settings?: Settings) => Diagnostic[]; doComplete?: (document: TextDocument, position: Position, settings?: Settings) => CompletionList; doResolve?: (document: TextDocument, item: CompletionItem) => CompletionItem; @@ -65,12 +63,9 @@ export interface LanguageModeRange extends Range { attributeValue?: boolean; } -export function getLanguageModes(supportedLanguages: { [languageId: string]: boolean; }, workspace: Workspace, customTags?: ITagSet, customAttributes?: IAttributeSet): LanguageModes { - - const htmlLanguageService = getHTMLLanguageService({ - customTags, - customAttributes - }); +export function getLanguageModes(supportedLanguages: { [languageId: string]: boolean; }, workspace: Workspace, clientCapabilities: ClientCapabilities, customDataProviders?: IHTMLDataProvider[]): LanguageModes { + const htmlLanguageService = getHTMLLanguageService({ customDataProviders, clientCapabilities }); + const cssLanguageService = getCSSLanguageService({ clientCapabilities }); let documentRegions = getLanguageModelCache(10, 60, document => getDocumentRegions(htmlLanguageService, document)); @@ -80,7 +75,7 @@ export function getLanguageModes(supportedLanguages: { [languageId: string]: boo let modes = Object.create(null); modes['html'] = getHTMLMode(htmlLanguageService, workspace); if (supportedLanguages['css']) { - modes['css'] = getCSSMode(documentRegions, workspace); + modes['css'] = getCSSMode(cssLanguageService, documentRegions, workspace); } if (supportedLanguages['javascript']) { modes['javascript'] = getJavaScriptMode(documentRegions); diff --git a/extensions/html-language-features/server/src/modes/pathCompletion.ts b/extensions/html-language-features/server/src/modes/pathCompletion.ts index cb3a20f8e4c..b7d7c1e7220 100644 --- a/extensions/html-language-features/server/src/modes/pathCompletion.ts +++ b/extensions/html-language-features/server/src/modes/pathCompletion.ts @@ -7,7 +7,7 @@ import { TextDocument, CompletionItemKind, CompletionItem, TextEdit, Range, Posi import { WorkspaceFolder } from 'vscode-languageserver'; import * as path from 'path'; import * as fs from 'fs'; -import URI from 'vscode-uri'; +import { URI } from 'vscode-uri'; import { ICompletionParticipant } from 'vscode-html-languageservice'; import { startsWith } from '../utils/strings'; import { contains } from '../utils/arrays'; @@ -108,11 +108,12 @@ function pathToSuggestion(p: string, valueBeforeCursor: string, fullValue: strin // Find the last slash before cursor, and calculate the start of replace range from there const valueAfterLastSlash = fullValue.slice(lastIndexOfSlash + 1); const startPos = shiftPosition(range.end, -1 - valueAfterLastSlash.length); - // If whitespace exists, replace until it - const whiteSpaceIndex = valueAfterLastSlash.indexOf(' '); + + // If whitespace exists, replace until there is no more + const whitespaceIndex = valueAfterLastSlash.indexOf(' '); let endPos; - if (whiteSpaceIndex !== -1) { - endPos = shiftPosition(startPos, whiteSpaceIndex); + if (whitespaceIndex !== -1) { + endPos = shiftPosition(startPos, whitespaceIndex); } else { endPos = shiftPosition(range.end, -1); } @@ -160,6 +161,7 @@ function shiftRange(range: Range, startOffset: number, endOffset: number): Range const PATH_TAG_AND_ATTR: { [tag: string]: string | string[] } = { // HTML 4 a: 'href', + area: 'href', body: 'background', del: 'cite', form: 'action', @@ -176,7 +178,7 @@ const PATH_TAG_AND_ATTR: { [tag: string]: string | string[] } = { command: 'icon', embed: 'src', html: 'manifest', - input: 'formaction', + input: ['src', 'formaction'], source: 'src', track: 'src', video: ['src', 'poster'] diff --git a/extensions/html-language-features/server/src/test/completions.test.ts b/extensions/html-language-features/server/src/test/completions.test.ts index c28daf9f0c2..aaba72add6d 100644 --- a/extensions/html-language-features/server/src/test/completions.test.ts +++ b/extensions/html-language-features/server/src/test/completions.test.ts @@ -5,10 +5,11 @@ import 'mocha'; import * as assert from 'assert'; import * as path from 'path'; -import Uri from 'vscode-uri'; +import { URI } from 'vscode-uri'; import { TextDocument, CompletionList, CompletionItemKind } from 'vscode-languageserver-types'; import { getLanguageModes } from '../modes/languageModes'; import { WorkspaceFolder } from 'vscode-languageserver'; +import { ClientCapabilities } from 'vscode-html-languageservice'; export interface ItemDescription { label: string; @@ -58,8 +59,8 @@ export function testCompletionFor(value: string, expected: { count?: number, ite let document = TextDocument.create(uri, 'html', 0, value); let position = document.positionAt(offset); - var languageModes = getLanguageModes({ css: true, javascript: true }, workspace); - var mode = languageModes.getModeAtPosition(document, position)!; + const languageModes = getLanguageModes({ css: true, javascript: true }, workspace, ClientCapabilities.LATEST); + const mode = languageModes.getModeAtPosition(document, position)!; let list = mode.doComplete!(document, position); @@ -95,9 +96,9 @@ suite('HTML Path Completion', () => { }; const fixtureRoot = path.resolve(__dirname, '../../src/test/pathCompletionFixtures'); - const fixtureWorkspace = { name: 'fixture', uri: Uri.file(fixtureRoot).toString() }; - const indexHtmlUri = Uri.file(path.resolve(fixtureRoot, 'index.html')).toString(); - const aboutHtmlUri = Uri.file(path.resolve(fixtureRoot, 'about/about.html')).toString(); + const fixtureWorkspace = { name: 'fixture', uri: URI.file(fixtureRoot).toString() }; + const indexHtmlUri = URI.file(path.resolve(fixtureRoot, 'index.html')).toString(); + const aboutHtmlUri = URI.file(path.resolve(fixtureRoot, 'about/about.html')).toString(); test('Basics - Correct label/kind/result/command', () => { testCompletionFor('", - "", - "", - "\t$0", - "", - "" - ], - "description": "Simple HTML5 starting point" - } -} diff --git a/extensions/html/syntaxes/html.tmLanguage.json b/extensions/html/syntaxes/html.tmLanguage.json index a5ccfed6f36..a071d90a9e3 100644 --- a/extensions/html/syntaxes/html.tmLanguage.json +++ b/extensions/html/syntaxes/html.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/textmate/html.tmbundle/commit/390c8870273a2ae80244dae6db6ba064a802f407", + "version": "https://github.com/textmate/html.tmbundle/commit/0c3d5ee54de3a993f747f54186b73a4d2d3c44a2", "name": "HTML", "scopeName": "text.html.basic", "injections": { @@ -222,7 +222,32 @@ ] } }, - "match": "[^\\n\"]+" + "match": "([^\\n\"/]|/(?![/*]))+" + }, + { + "begin": "//", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.js" + } + }, + "end": "(?=\")|\\n", + "name": "comment.line.double-slash.js" + }, + { + "begin": "/\\*", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.begin.js" + } + }, + "end": "(?=\")|\\*/", + "endCaptures": { + "0": { + "name": "punctuation.definition.comment.end.js" + } + }, + "name": "comment.block.js" } ] }, @@ -255,7 +280,32 @@ ] } }, - "match": "[^\\n']+" + "match": "([^\\n'/]|/(?![/*]))+" + }, + { + "begin": "//", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.js" + } + }, + "end": "(?=')|\\n", + "name": "comment.line.double-slash.js" + }, + { + "begin": "/\\*", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.begin.js" + } + }, + "end": "(?=')|\\*/", + "endCaptures": { + "0": { + "name": "punctuation.definition.comment.end.js" + } + }, + "name": "comment.block.js" } ] } diff --git a/extensions/ini/cgmanifest.json b/extensions/ini/cgmanifest.json index ef9fa28b58a..772dc25a3ac 100644 --- a/extensions/ini/cgmanifest.json +++ b/extensions/ini/cgmanifest.json @@ -29,4 +29,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/ini/package.json b/extensions/ini/package.json index ea3df33d8df..cc5ca5da606 100644 --- a/extensions/ini/package.json +++ b/extensions/ini/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js textmate/ini.tmbundle Syntaxes/Ini.plist ./syntaxes/ini.tmLanguage.json" @@ -17,8 +18,9 @@ }, { "id": "properties", - "extensions": [ ".properties", ".cfg", ".conf", ".desktop", ".directory" ], - "filenames": [ "config", ".gitattributes", ".gitconfig", "gitconfig", ".editorconfig" ], + "extensions": [ ".properties", ".cfg", ".conf", ".directory" ], + "filenames": [ ".gitattributes", ".gitconfig", "gitconfig", ".gitmodules", ".editorconfig" ], + "filenamePatterns": [ "**/.config/git/config", "**/.git/config" ], "aliases": [ "Properties", "properties" ], "configuration": "./properties.language-configuration.json" }], diff --git a/extensions/jake/package.json b/extensions/jake/package.json index f35e49fee26..1b1af72106b 100644 --- a/extensions/jake/package.json +++ b/extensions/jake/package.json @@ -5,6 +5,7 @@ "displayName": "%displayName%", "icon": "images/cowboy_hat.png", "version": "1.0.0", + "license": "MIT", "engines": { "vscode": "*" }, @@ -19,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^8.10.25" + "@types/node": "^10.14.8" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/jake/src/main.ts b/extensions/jake/src/main.ts index d778dcedab7..b8c6d5e7344 100644 --- a/extensions/jake/src/main.ts +++ b/extensions/jake/src/main.ts @@ -60,12 +60,25 @@ function getOutputChannel(): vscode.OutputChannel { } function showError() { - vscode.window.showWarningMessage(localize('gulpTaskDetectError', 'Problem finding jake tasks. See the output for more information.'), + vscode.window.showWarningMessage(localize('jakeTaskDetectError', 'Problem finding jake tasks. See the output for more information.'), localize('jakeShowOutput', 'Go to output')).then(() => { getOutputChannel().show(true); }); } +async function findJakeCommand(rootPath: string): Promise { + let jakeCommand: string; + let platform = process.platform; + if (platform === 'win32' && await exists(path.join(rootPath!, 'node_modules', '.bin', 'jake.cmd'))) { + jakeCommand = path.join('.', 'node_modules', '.bin', 'jake.cmd'); + } else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(rootPath!, 'node_modules', '.bin', 'jake'))) { + jakeCommand = path.join('.', 'node_modules', '.bin', 'jake'); + } else { + jakeCommand = 'jake'; + } + return jakeCommand; +} + interface JakeTaskDefinition extends vscode.TaskDefinition { task: string; file?: string; @@ -76,7 +89,9 @@ class FolderDetector { private fileWatcher: vscode.FileSystemWatcher | undefined; private promise: Thenable | undefined; - constructor(private _workspaceFolder: vscode.WorkspaceFolder) { + constructor( + private _workspaceFolder: vscode.WorkspaceFolder, + private _jakeCommand: Promise) { } public get workspaceFolder(): vscode.WorkspaceFolder { @@ -96,10 +111,25 @@ class FolderDetector { } public async getTasks(): Promise { - if (!this.promise) { - this.promise = this.computeTasks(); + if (this.isEnabled()) { + if (!this.promise) { + this.promise = this.computeTasks(); + } + return this.promise; + } else { + return []; } - return this.promise; + } + + public async getTask(_task: vscode.Task): Promise { + const jakeTask = (_task.definition).task; + if (jakeTask) { + let kind: JakeTaskDefinition = (_task.definition); + let options: vscode.ShellExecutionOptions = { cwd: this.workspaceFolder.uri.fsPath }; + let task = new vscode.Task(kind, this.workspaceFolder, jakeTask, 'jake', new vscode.ShellExecution(await this._jakeCommand, [jakeTask], options)); + return task; + } + return undefined; } private async computeTasks(): Promise { @@ -116,17 +146,7 @@ class FolderDetector { } } - let jakeCommand: string; - let platform = process.platform; - if (platform === 'win32' && await exists(path.join(rootPath!, 'node_modules', '.bin', 'jake.cmd'))) { - jakeCommand = path.join('.', 'node_modules', '.bin', 'jake.cmd'); - } else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(rootPath!, 'node_modules', '.bin', 'jake'))) { - jakeCommand = path.join('.', 'node_modules', '.bin', 'jake'); - } else { - jakeCommand = 'jake'; - } - - let commandLine = `${jakeCommand} --tasks`; + let commandLine = `${await this._jakeCommand} --tasks`; try { let { stdout, stderr } = await exec(commandLine, { cwd: rootPath }); if (stderr) { @@ -149,7 +169,7 @@ class FolderDetector { task: taskName }; let options: vscode.ShellExecutionOptions = { cwd: this.workspaceFolder.uri.fsPath }; - let task = new vscode.Task(kind, taskName, 'jake', new vscode.ShellExecution(`${jakeCommand} ${taskName}`, options)); + let task = new vscode.Task(kind, taskName, 'jake', new vscode.ShellExecution(`${await this._jakeCommand} ${taskName}`, options)); result.push(task); let lowerCaseLine = line.toLowerCase(); if (isBuildTask(lowerCaseLine)) { @@ -208,7 +228,7 @@ class TaskDetector { this.detectors.clear(); } - private updateWorkspaceFolders(added: vscode.WorkspaceFolder[], removed: vscode.WorkspaceFolder[]): void { + private updateWorkspaceFolders(added: readonly vscode.WorkspaceFolder[], removed: readonly vscode.WorkspaceFolder[]): void { for (let remove of removed) { let detector = this.detectors.get(remove.uri.toString()); if (detector) { @@ -217,9 +237,9 @@ class TaskDetector { } } for (let add of added) { - let detector = new FolderDetector(add); + let detector = new FolderDetector(add, findJakeCommand(add.uri.fsPath)); + this.detectors.set(add.uri.toString(), detector); if (detector.isEnabled()) { - this.detectors.set(add.uri.toString(), detector); detector.start(); } } @@ -228,18 +248,16 @@ class TaskDetector { private updateConfiguration(): void { for (let detector of this.detectors.values()) { - if (!detector.isEnabled()) { - detector.dispose(); - this.detectors.delete(detector.workspaceFolder.uri.toString()); - } + detector.dispose(); + this.detectors.delete(detector.workspaceFolder.uri.toString()); } let folders = vscode.workspace.workspaceFolders; if (folders) { for (let folder of folders) { if (!this.detectors.has(folder.uri.toString())) { - let detector = new FolderDetector(folder); + let detector = new FolderDetector(folder, findJakeCommand(folder.uri.fsPath)); + this.detectors.set(folder.uri.toString(), detector); if (detector.isEnabled()) { - this.detectors.set(folder.uri.toString(), detector); detector.start(); } } @@ -250,12 +268,13 @@ class TaskDetector { private updateProvider(): void { if (!this.taskProvider && this.detectors.size > 0) { - this.taskProvider = vscode.workspace.registerTaskProvider('gulp', { - provideTasks: () => { - return this.getTasks(); + const thisCapture = this; + this.taskProvider = vscode.workspace.registerTaskProvider('jake', { + provideTasks(): Promise { + return thisCapture.getTasks(); }, - resolveTask(_task: vscode.Task): vscode.Task | undefined { - return undefined; + resolveTask(_task: vscode.Task): Promise { + return thisCapture.getTask(_task); } }); } @@ -290,6 +309,25 @@ class TaskDetector { }); } } + + public async getTask(task: vscode.Task): Promise { + if (this.detectors.size === 0) { + return undefined; + } else if (this.detectors.size === 1) { + return this.detectors.values().next().value.getTask(task); + } else { + if ((task.scope === vscode.TaskScope.Workspace) || (task.scope === vscode.TaskScope.Global)) { + // Not supported, we don't have enough info to create the task. + return undefined; + } else if (task.scope) { + const detector = this.detectors.get(task.scope.uri.toString()); + if (detector) { + return detector.getTask(task); + } + } + return undefined; + } + } } let detector: TaskDetector; @@ -300,4 +338,4 @@ export function activate(_context: vscode.ExtensionContext): void { export function deactivate(): void { detector.dispose(); -} \ No newline at end of file +} diff --git a/extensions/jake/yarn.lock b/extensions/jake/yarn.lock index 5e39a356be6..e6247e29255 100644 --- a/extensions/jake/yarn.lock +++ b/extensions/jake/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/java/cgmanifest.json b/extensions/java/cgmanifest.json index ba162b137ab..9a5b5fab2b5 100644 --- a/extensions/java/cgmanifest.json +++ b/extensions/java/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "atom/language-java", "repositoryUrl": "https://github.com/atom/language-java", - "commitHash": "7c3d0d3e37920790cd3afb4e68830bdb215851a3" + "commitHash": "759a0ac02dc091018a112b25a5a6d894918a0aa8" } }, "license": "MIT", - "version": "0.31.1" + "version": "0.31.3" } ], "version": 1 diff --git a/extensions/java/package.json b/extensions/java/package.json index fe023218a8f..9d3310681b9 100644 --- a/extensions/java/package.json +++ b/extensions/java/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js atom/language-java grammars/java.cson ./syntaxes/java.tmLanguage.json" diff --git a/extensions/java/syntaxes/java.tmLanguage.json b/extensions/java/syntaxes/java.tmLanguage.json index 650a82c63be..6b4233c8eb3 100644 --- a/extensions/java/syntaxes/java.tmLanguage.json +++ b/extensions/java/syntaxes/java.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/atom/language-java/commit/7c3d0d3e37920790cd3afb4e68830bdb215851a3", + "version": "https://github.com/atom/language-java/commit/759a0ac02dc091018a112b25a5a6d894918a0aa8", "name": "Java", "scopeName": "source.java", "patterns": [ @@ -124,15 +124,15 @@ "annotations": { "patterns": [ { - "begin": "((@)[^\\s(]+)(\\()", + "begin": "((@)\\s*([^\\s(]+))(\\()", "beginCaptures": { - "1": { - "name": "storage.type.annotation.java" - }, "2": { "name": "punctuation.definition.annotation.java" }, "3": { + "name": "storage.type.annotation.java" + }, + "4": { "name": "punctuation.definition.annotation-arguments.begin.bracket.round.java" } }, @@ -161,7 +161,7 @@ ] }, { - "match": "(@)(interface)\\s+(\\w*)|((@)\\w*)", + "match": "(@)(interface)\\s+(\\w*)|((@)\\s*(\\w+))", "name": "meta.declaration.annotation.java", "captures": { "1": { @@ -173,11 +173,11 @@ "3": { "name": "storage.type.annotation.java" }, - "4": { - "name": "storage.type.annotation.java" - }, "5": { "name": "punctuation.definition.annotation.java" + }, + "6": { + "name": "storage.type.annotation.java" } } } @@ -209,7 +209,7 @@ "name": "keyword.control.new.java" } }, - "end": "(?=;|\\)|,|:|}|\\+)", + "end": "(?=;|\\)|,|:|}|\\+|\\-|\\*|\\/|%|!|&|\\||=)", "patterns": [ { "include": "#comments" @@ -640,6 +640,42 @@ }, "name": "meta.enum.java", "patterns": [ + { + "begin": "\\b(extends)\\b", + "beginCaptures": { + "1": { + "name": "storage.modifier.extends.java" + } + }, + "end": "(?={|\\bimplements\\b)", + "name": "meta.definition.class.inherited.classes.java", + "patterns": [ + { + "include": "#object-types-inherited" + }, + { + "include": "#comments" + } + ] + }, + { + "begin": "\\b(implements)\\b", + "beginCaptures": { + "1": { + "name": "storage.modifier.implements.java" + } + }, + "end": "(?={|\\bextends\\b)", + "name": "meta.definition.class.implemented.interfaces.java", + "patterns": [ + { + "include": "#object-types-inherited" + }, + { + "include": "#comments" + } + ] + }, { "begin": "{", "beginCaptures": { @@ -1060,12 +1096,12 @@ "include": "#generics" }, { - "begin": "\\b((?:[A-Za-z]\\w*\\s*\\.\\s*)*)([A-Z]\\w*)\\s*(?=\\[)", + "begin": "\\b((?:[A-Za-z_]\\w*\\s*\\.\\s*)*)([A-Z_]\\w*)\\s*(?=\\[)", "beginCaptures": { "1": { "patterns": [ { - "match": "[A-Za-z]\\w*", + "match": "[A-Za-z_]\\w*", "name": "storage.type.java" }, { @@ -1089,12 +1125,12 @@ ] }, { - "match": "\\b((?:[A-Za-z]\\w*\\s*\\.\\s*)*[A-Z]\\w*)\\s*(?=<)", + "match": "\\b((?:[A-Za-z_]\\w*\\s*\\.\\s*)*[A-Z_]\\w*)\\s*(?=<)", "captures": { "1": { "patterns": [ { - "match": "[A-Za-z]\\w*", + "match": "[A-Za-z_]\\w*", "name": "storage.type.java" }, { @@ -1106,12 +1142,12 @@ } }, { - "match": "\\b((?:[A-Za-z]\\w*\\s*\\.\\s*)*[A-Z]\\w*)\\b((?=\\s*[A-Za-z$_\\n])|(?=\\s*\\.\\.\\.))", + "match": "\\b((?:[A-Za-z_]\\w*\\s*\\.\\s*)*[A-Z_]\\w*)\\b((?=\\s*[A-Za-z$_\\n])|(?=\\s*\\.\\.\\.))", "captures": { "1": { "patterns": [ { - "match": "[A-Za-z]\\w*", + "match": "[A-Za-z_]\\w*", "name": "storage.type.java" }, { @@ -1468,6 +1504,9 @@ { "include": "#comments" }, + { + "include": "#storage-modifiers" + }, { "match": "\\|", "name": "punctuation.catch.separator.java" @@ -1537,7 +1576,7 @@ ] }, "variables": { - "begin": "(?x)\n(?=\n (\n \\b(void|boolean|byte|char|short|int|float|long|double)\\b\n |\n (?>(\\w+\\.)*[A-Z]+\\w*) # e.g. `javax.ws.rs.Response`, or `String`\n )\n (\n <[\\w<>,\\.?\\s\\[\\]]*> # e.g. `HashMap`, or `List`\n )?\n (\n (\\[\\])* # int[][]\n )?\n \\s+\n [A-Za-z_$][\\w$]* # At least one identifier after space\n ([\\w\\[\\],$][\\w\\[\\],\\s]*)? # possibly primitive array or additional identifiers\n \\s*(=|:|;)\n)", + "begin": "(?x)\n(?=\n (\n \\b(void|boolean|byte|char|short|int|float|long|double)\\b\n |\n (?>(\\w+\\.)*[A-Z_]+\\w*) # e.g. `javax.ws.rs.Response`, or `String`\n )\n \\s*\n (\n <[\\w<>,\\.?\\s\\[\\]]*> # e.g. `HashMap`, or `List`\n )?\n \\s*\n (\n (\\[\\])* # int[][]\n )?\n \\s+\n [A-Za-z_$][\\w$]* # At least one identifier after space\n ([\\w\\[\\],$][\\w\\[\\],\\s]*)? # possibly primitive array or additional identifiers\n \\s*(=|:|;)\n)", "end": "(?=\\=|:|;)", "name": "meta.definition.variable.java", "patterns": [ diff --git a/extensions/java/test/colorize-results/basic_java.json b/extensions/java/test/colorize-results/basic_java.json index b41a14df569..0032d405471 100644 --- a/extensions/java/test/colorize-results/basic_java.json +++ b/extensions/java/test/colorize-results/basic_java.json @@ -1068,13 +1068,13 @@ }, { "c": "@", - "t": "source.java meta.class.java meta.class.body.java meta.declaration.annotation.java storage.type.annotation.java punctuation.definition.annotation.java", + "t": "source.java meta.class.java meta.class.body.java meta.declaration.annotation.java punctuation.definition.annotation.java", "r": { - "dark_plus": "storage.type.annotation.java: #4EC9B0", - "light_plus": "storage.type.annotation.java: #267F99", - "dark_vs": "storage.type: #569CD6", - "light_vs": "storage.type: #0000FF", - "hc_black": "storage.type.annotation.java: #4EC9B0" + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" } }, { @@ -1871,13 +1871,13 @@ }, { "c": "@", - "t": "source.java meta.class.java meta.class.body.java meta.declaration.annotation.java storage.type.annotation.java punctuation.definition.annotation.java", + "t": "source.java meta.class.java meta.class.body.java meta.declaration.annotation.java punctuation.definition.annotation.java", "r": { - "dark_plus": "storage.type.annotation.java: #4EC9B0", - "light_plus": "storage.type.annotation.java: #267F99", - "dark_vs": "storage.type: #569CD6", - "light_vs": "storage.type: #0000FF", - "hc_black": "storage.type.annotation.java: #4EC9B0" + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" } }, { diff --git a/extensions/javascript/package.json b/extensions/javascript/package.json index c60988f88fe..6909de1400f 100644 --- a/extensions/javascript/package.json +++ b/extensions/javascript/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "0.10.x" }, diff --git a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json index bbe77ae2db9..ed16712a061 100644 --- a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/f17fefd8d6bbf181ea27be2faccb2a274366e6db", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/84238ef0fa1c7e4e2c9fe77875d832dab9f57e5d", "name": "JavaScript (with React support)", "scopeName": "source.js", "patterns": [ @@ -132,6 +132,9 @@ "name": "keyword.control.switch.js", "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js entity.name.function.js" @@ -432,7 +435,7 @@ "name": "keyword.operator.definiteassignment.js" } }, - "end": "(?=$|^|[;,=}]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[;,=}]|((?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js variable.other.constant.js entity.name.function.js" } }, - "end": "(?=$|^|[;,=}]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[;,=}]|((?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js" @@ -953,7 +968,7 @@ "include": "#comment" }, { - "begin": "(?x)(?=((\\b(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "meta.definition.property.js entity.name.function.js" @@ -1123,7 +1144,7 @@ "name": "keyword.operator.assignment.js" } }, - "end": "(?=$|^|[,);}\\]]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[,);}\\]]|((?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.js" @@ -1297,7 +1318,7 @@ }, { "name": "meta.method.declaration.js", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.js" @@ -1329,7 +1350,7 @@ }, "object-literal-method-declaration": { "name": "meta.method.declaration.js", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -1350,7 +1371,7 @@ "include": "#function-body" }, { - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -1372,7 +1393,7 @@ ] }, "method-declaration-name": { - "begin": "(?x)(?=((\\b(? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -1563,7 +1584,7 @@ "include": "#parameter-name" }, { - "include": "#type-annotation" + "include": "#parameter-type-annotation" }, { "include": "#variable-initializer" @@ -1600,9 +1621,12 @@ }, "class-expression": { "name": "meta.class.js", - "begin": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*:(\\s*\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/)*\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.js" @@ -2540,6 +2647,33 @@ } } }, + { + "name": "meta.object.member.js", + "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)\\(\\s*([\\{\\[]\\s*)?$)", + "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*([\\{\\[]\\s*)?$)", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -2615,6 +2749,9 @@ } ] }, + { + "include": "#possibly-arrow-return-type" + }, { "include": "#expression" } @@ -2654,20 +2791,7 @@ "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()", "patterns": [ { - "include": "#literal" - }, - { - "include": "#support-objects" - }, - { - "include": "#object-identifiers" - }, - { - "include": "#punctuation-accessor" - }, - { - "name": "keyword.operator.expression.import.js", - "match": "(?:(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*))?\\(\\s*[\\{\\[]\\s*$)", + "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*[\\{\\[]\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -2742,7 +2886,7 @@ ] }, { - "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*))?\\()|(<))\\s*$)", + "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -2812,7 +2956,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js" @@ -2958,6 +3102,17 @@ "name": "keyword.operator.expression.void.js", "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", "captures": { "1": { "name": "punctuation.accessor.js" @@ -3389,7 +3558,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.js" @@ -3510,6 +3679,25 @@ } ] }, + "parameter-type-annotation": { + "patterns": [ + { + "name": "meta.type.annotation.js", + "begin": "(:)", + "beginCaptures": { + "1": { + "name": "keyword.operator.type.annotation.js" + } + }, + "end": "(?=[,)])|(?==[^>])", + "patterns": [ + { + "include": "#type" + } + ] + } + ] + }, "return-type": { "patterns": [ { @@ -3582,7 +3770,7 @@ ] }, "possibly-arrow-return-type": { - "begin": "(?<=\\)|^)\\s*(:)(?=\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*=>)", + "begin": "(?<=\\)|^)\\s*(:)(?=\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*=>)", "beginCaptures": { "1": { "name": "meta.arrow.js meta.return.type.arrow.js keyword.operator.type.annotation.js" @@ -3728,6 +3916,14 @@ { "include": "#type-function-return-type" }, + { + "match": "(?\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "end": "(?=`)", + "patterns": [ + { + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", + "end": "(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "patterns": [ + { + "include": "#support-function-call-identifiers" + }, + { + "name": "entity.name.function.tagged-template.js", + "match": "([_$[:alpha:]][_$[:alnum:]]*)" + } + ] + }, + { + "include": "#type-arguments" + } + ] + }, { "name": "string.template.js", "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", @@ -4304,7 +4523,7 @@ "patterns": [ { "name": "string.regexp.js", - "begin": "(?|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))", + "begin": "(?|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.js" @@ -4327,7 +4546,7 @@ }, { "name": "string.regexp.js", - "begin": "(?\\s*$)", + "begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`)))+\\s*/>\\s*$)", "beginCaptures": { "1": { "name": "punctuation.definition.comment.js" @@ -5056,10 +5275,6 @@ }, "jsdoctype": { "patterns": [ - { - "name": "invalid.illegal.type.jsdoc", - "match": "\\G{(?:[^}*]|\\*[^/}])+$" - }, { "contentName": "entity.name.type.instance.jsdoc", "begin": "\\G({)", @@ -5099,7 +5314,7 @@ ] }, "jsx-tag-without-attributes-in-expression": { - "begin": "(?:*]|&&|\\|\\||\\?|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*(?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", + "begin": "(?:*]|&&|\\|\\||\\?|\\*\\/|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*(?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "end": "(?!(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "patterns": [ { @@ -5159,7 +5374,7 @@ ] }, "jsx-tag-in-expression": { - "begin": "(?x)\n (?:*]|&&|\\|\\||\\?|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", + "begin": "(?x)\n (?:*]|&&|\\|\\||\\?|\\*\\/|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "end": "(?!(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "patterns": [ { diff --git a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json index cfd20d75e47..ee685716166 100644 --- a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/f17fefd8d6bbf181ea27be2faccb2a274366e6db", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/84238ef0fa1c7e4e2c9fe77875d832dab9f57e5d", "name": "JavaScript (with React support)", "scopeName": "source.js.jsx", "patterns": [ @@ -132,6 +132,9 @@ "name": "keyword.control.switch.js.jsx", "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js.jsx entity.name.function.js.jsx" @@ -432,7 +435,7 @@ "name": "keyword.operator.definiteassignment.js.jsx" } }, - "end": "(?=$|^|[;,=}]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[;,=}]|((?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js.jsx variable.other.constant.js.jsx entity.name.function.js.jsx" } }, - "end": "(?=$|^|[;,=}]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[;,=}]|((?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js.jsx" @@ -953,7 +968,7 @@ "include": "#comment" }, { - "begin": "(?x)(?=((\\b(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "meta.definition.property.js.jsx entity.name.function.js.jsx" @@ -1123,7 +1144,7 @@ "name": "keyword.operator.assignment.js.jsx" } }, - "end": "(?=$|^|[,);}\\]]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[,);}\\]]|((?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.js.jsx" @@ -1297,7 +1318,7 @@ }, { "name": "meta.method.declaration.js.jsx", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.js.jsx" @@ -1329,7 +1350,7 @@ }, "object-literal-method-declaration": { "name": "meta.method.declaration.js.jsx", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -1350,7 +1371,7 @@ "include": "#function-body" }, { - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -1372,7 +1393,7 @@ ] }, "method-declaration-name": { - "begin": "(?x)(?=((\\b(? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -1563,7 +1584,7 @@ "include": "#parameter-name" }, { - "include": "#type-annotation" + "include": "#parameter-type-annotation" }, { "include": "#variable-initializer" @@ -1600,9 +1621,12 @@ }, "class-expression": { "name": "meta.class.js.jsx", - "begin": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*:(\\s*\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/)*\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.js.jsx" @@ -2540,6 +2647,33 @@ } } }, + { + "name": "meta.object.member.js.jsx", + "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)\\(\\s*([\\{\\[]\\s*)?$)", + "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*([\\{\\[]\\s*)?$)", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -2615,6 +2749,9 @@ } ] }, + { + "include": "#possibly-arrow-return-type" + }, { "include": "#expression" } @@ -2654,20 +2791,7 @@ "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()", "patterns": [ { - "include": "#literal" - }, - { - "include": "#support-objects" - }, - { - "include": "#object-identifiers" - }, - { - "include": "#punctuation-accessor" - }, - { - "name": "keyword.operator.expression.import.js.jsx", - "match": "(?:(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*))?\\(\\s*[\\{\\[]\\s*$)", + "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*[\\{\\[]\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -2742,7 +2886,7 @@ ] }, { - "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*))?\\()|(<))\\s*$)", + "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.js.jsx" @@ -2812,7 +2956,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js.jsx" @@ -2958,6 +3102,17 @@ "name": "keyword.operator.expression.void.js.jsx", "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", "captures": { "1": { "name": "punctuation.accessor.js.jsx" @@ -3389,7 +3558,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.js.jsx" @@ -3510,6 +3679,25 @@ } ] }, + "parameter-type-annotation": { + "patterns": [ + { + "name": "meta.type.annotation.js.jsx", + "begin": "(:)", + "beginCaptures": { + "1": { + "name": "keyword.operator.type.annotation.js.jsx" + } + }, + "end": "(?=[,)])|(?==[^>])", + "patterns": [ + { + "include": "#type" + } + ] + } + ] + }, "return-type": { "patterns": [ { @@ -3582,7 +3770,7 @@ ] }, "possibly-arrow-return-type": { - "begin": "(?<=\\)|^)\\s*(:)(?=\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*=>)", + "begin": "(?<=\\)|^)\\s*(:)(?=\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*=>)", "beginCaptures": { "1": { "name": "meta.arrow.js.jsx meta.return.type.arrow.js.jsx keyword.operator.type.annotation.js.jsx" @@ -3728,6 +3916,14 @@ { "include": "#type-function-return-type" }, + { + "match": "(?\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "end": "(?=`)", + "patterns": [ + { + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", + "end": "(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "patterns": [ + { + "include": "#support-function-call-identifiers" + }, + { + "name": "entity.name.function.tagged-template.js.jsx", + "match": "([_$[:alpha:]][_$[:alnum:]]*)" + } + ] + }, + { + "include": "#type-arguments" + } + ] + }, { "name": "string.template.js.jsx", "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", @@ -4304,7 +4523,7 @@ "patterns": [ { "name": "string.regexp.js.jsx", - "begin": "(?|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))", + "begin": "(?|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.js.jsx" @@ -4327,7 +4546,7 @@ }, { "name": "string.regexp.js.jsx", - "begin": "(?\\s*$)", + "begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`)))+\\s*/>\\s*$)", "beginCaptures": { "1": { "name": "punctuation.definition.comment.js.jsx" @@ -5056,10 +5275,6 @@ }, "jsdoctype": { "patterns": [ - { - "name": "invalid.illegal.type.jsdoc", - "match": "\\G{(?:[^}*]|\\*[^/}])+$" - }, { "contentName": "entity.name.type.instance.jsdoc", "begin": "\\G({)", @@ -5099,7 +5314,7 @@ ] }, "jsx-tag-without-attributes-in-expression": { - "begin": "(?:*]|&&|\\|\\||\\?|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*(?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", + "begin": "(?:*]|&&|\\|\\||\\?|\\*\\/|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*(?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "end": "(?!(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "patterns": [ { @@ -5159,7 +5374,7 @@ ] }, "jsx-tag-in-expression": { - "begin": "(?x)\n (?:*]|&&|\\|\\||\\?|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", + "begin": "(?x)\n (?:*]|&&|\\|\\||\\?|\\*\\/|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "end": "(?!(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "patterns": [ { diff --git a/extensions/json-language-features/.vscode/launch.json b/extensions/json-language-features/.vscode/launch.json index b2d26ad6c35..bb5cde48bfd 100644 --- a/extensions/json-language-features/.vscode/launch.json +++ b/extensions/json-language-features/.vscode/launch.json @@ -33,6 +33,14 @@ "sourceMaps": true, "outFiles": ["${workspaceFolder}/server/out"] } - + ], + "compounds": [ + { + "name": "Launch Extension and Attach Language Server", + "configurations": [ + "Launch Extension", + "Attach Language Server" + ] + } ] } \ No newline at end of file diff --git a/extensions/json-language-features/.vscodeignore b/extensions/json-language-features/.vscodeignore index b3cba2c6a80..3011e9dcd0a 100644 --- a/extensions/json-language-features/.vscodeignore +++ b/extensions/json-language-features/.vscodeignore @@ -13,5 +13,6 @@ server/build/** server/yarn.lock server/.npmignore yarn.lock +CONTRIBUTING.md server/extension.webpack.config.js extension.webpack.config.js \ No newline at end of file diff --git a/extensions/json-language-features/CONTRIBUTING.md b/extensions/json-language-features/CONTRIBUTING.md new file mode 100644 index 00000000000..90367dec71e --- /dev/null +++ b/extensions/json-language-features/CONTRIBUTING.md @@ -0,0 +1,39 @@ +## Setup + +- Clone [Microsoft/vscode](https://github.com/microsoft/vscode) +- Run `yarn` at `/`, this will install + - Dependencies for `/extension/json-language-features/` + - Dependencies for `/extension/json-language-features/server/` + - devDependencies such as `gulp` +- Open `/extensions/json-language-features/` as the workspace in VS Code +- Run the [`Launch Extension`](https://github.com/Microsoft/vscode/blob/master/extensions/json-language-features/.vscode/launch.json) debug target in the Debug View. This will: + - Launch the `preLaunchTask` task to compile the extension + - Launch a new VS Code instance with the `json-language-features` extension loaded + - You should see a notification saying the development version of `json-language-features` overwrites the bundled version of `json-language-features` +- Open a `.json` file to activate the extension. The extension will start the JSON language server process. +- Add `"json.trace.server": "verbose"` to the settings to observe the communication between client and server. +- Debug the language server process by using `Attach to Node Process` command in the VS Code window opened on `json-language-features` +- Run `Reload Window` command in the launched instance to reload the extension + + +### Contribute to vscode-json-languageservice + +[Microsoft/vscode-json-languageservice](https://github.com/Microsoft/vscode-json-languageservice) is the library that implements the language smarts for JSON. +The JSON language server forwards most the of requests to the service library. +If you want to fix JSON issues or make improvements, you should make changes at [Microsoft/vscode-json-languageservice](https://github.com/Microsoft/vscode-json-languageservice). + +However, within this extension, you can run a development version of `vscode-json-languageservice` to debug code or test language features interactively: + +#### Linking `vscode-json-languageservice` in `json-language-features/server/` + +- Clone [Microsoft/vscode-json-languageservice](https://github.com/Microsoft/vscode-json-languageservice) +- Run `npm install` in `vscode-json-languageservice` +- Run `npm link` in `vscode-json-languageservice`. This will compile and link `vscode-json-languageservice` +- In `json-language-features/server/`, run `yarn link vscode-json-languageservice` + +#### Testing the development version of `vscode-json-languageservice` + +- Open both `vscode-json-languageservice` and this extension in a single workspace with [multi-root workspace](https://code.visualstudio.com/docs/editor/multi-root-workspaces) feature +- Run `yarn watch` at `json-languagefeatures/server/` to recompile this extension with the linked version of `vscode-json-languageservice` +- Make some changes in `vscode-json-languageservice` +- Now when you run `Launch Extension` debug target, the launched instance will use your development version of `vscode-json-languageservice`. You can interactively test the language features. \ No newline at end of file diff --git a/extensions/json-language-features/client/src/jsonMain.ts b/extensions/json-language-features/client/src/jsonMain.ts index 79d30295ff1..6f1ca02d580 100644 --- a/extensions/json-language-features/client/src/jsonMain.ts +++ b/extensions/json-language-features/client/src/jsonMain.ts @@ -6,10 +6,12 @@ import * as path from 'path'; import * as fs from 'fs'; import * as nls from 'vscode-nls'; +import { xhr, XHRResponse, getErrorStatusDescription } from 'request-light'; + const localize = nls.loadMessageBundle(); import { workspace, window, languages, commands, ExtensionContext, extensions, Uri, LanguageConfiguration, Diagnostic, StatusBarAlignment, TextEditor } from 'vscode'; -import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification, HandleDiagnosticsSignature } from 'vscode-languageclient'; +import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification, HandleDiagnosticsSignature, ResponseError } from 'vscode-languageclient'; import TelemetryReporter from 'vscode-extension-telemetry'; import { hash } from './utils/hash'; @@ -81,7 +83,12 @@ export function activate(context: ExtensionContext) { let documentSelector = ['json', 'jsonc']; - let schemaResolutionErrorStatusBarItem = window.createStatusBarItem(StatusBarAlignment.Right, 0); + let schemaResolutionErrorStatusBarItem = window.createStatusBarItem({ + id: 'status.json.resolveError', + name: localize('json.resolveError', "JSON: Schema Resolution Error"), + alignment: StatusBarAlignment.Right, + priority: 0 + }); schemaResolutionErrorStatusBarItem.command = '_json.retryResolveSchema'; schemaResolutionErrorStatusBarItem.tooltip = localize('json.schemaResolutionErrorMessage', 'Unable to resolve schema.') + ' ' + localize('json.clickToRetry', 'Click to retry.'); schemaResolutionErrorStatusBarItem.text = '$(alert)'; @@ -93,6 +100,9 @@ export function activate(context: ExtensionContext) { let clientOptions: LanguageClientOptions = { // Register the server for json documents documentSelector, + initializationOptions: { + handledSchemaProtocols: ['file'] // language server only loads file-URI. Fetching schemas with other protocols ('http'...) are made on the client. + }, synchronize: { // Synchronize the setting section 'json' to the server configurationSection: ['json', 'http'], @@ -138,11 +148,20 @@ export function activate(context: ExtensionContext) { // handle content request client.onRequest(VSCodeContentRequest.type, (uriPath: string) => { let uri = Uri.parse(uriPath); - return workspace.openTextDocument(uri).then(doc => { - return doc.getText(); - }, error => { - return Promise.reject(error); - }); + if (uri.scheme !== 'http' && uri.scheme !== 'https') { + return workspace.openTextDocument(uri).then(doc => { + return doc.getText(); + }, error => { + return Promise.reject(error); + }); + } else { + const headers = { 'Accept-Encoding': 'gzip, deflate' }; + return xhr({ url: uriPath, followRedirects: 5, headers }).then(response => { + return response.responseText; + }, (error: XHRResponse) => { + return Promise.reject(new ResponseError(error.status, error.responseText || getErrorStatusDescription(error.status) || error.toString())); + }); + } }); let handleContentChange = (uri: Uri) => { @@ -193,12 +212,18 @@ export function activate(context: ExtensionContext) { toDispose.push(commands.registerCommand('_json.retryResolveSchema', handleRetryResolveSchemaCommand)); client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context)); + + extensions.onDidChange(_ => { + client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context)); + }); }); + + let languageConfiguration: LanguageConfiguration = { wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/, indentationRules: { - increaseIndentPattern: /^.*(\{[^}]*|\[[^\]]*)$/, + increaseIndentPattern: /({+(?=([^"]*"[^"]*")*[^"}]*$))|(\[+(?=([^"]*"[^"]*")*[^"\]]*$))/, decreaseIndentPattern: /^\s*[}\]],?\s*$/ } }; @@ -225,6 +250,7 @@ function getSchemaAssociation(_context: ExtensionContext): ISchemaAssociations { } if (fileMatch[0] === '%') { fileMatch = fileMatch.replace(/%APP_SETTINGS_HOME%/, '/User'); + fileMatch = fileMatch.replace(/%MACHINE_SETTINGS_HOME%/, '/Machine'); fileMatch = fileMatch.replace(/%APP_WORKSPACES_HOME%/, '/Workspaces'); } else if (fileMatch.charAt(0) !== '/' && !fileMatch.match(/\w+:\/\//)) { fileMatch = '/' + fileMatch; diff --git a/extensions/json-language-features/client/src/typings/ref.d.ts b/extensions/json-language-features/client/src/typings/ref.d.ts index 9c1a5df18ed..be1d1b0b776 100644 --- a/extensions/json-language-features/client/src/typings/ref.d.ts +++ b/extensions/json-language-features/client/src/typings/ref.d.ts @@ -4,3 +4,4 @@ *--------------------------------------------------------------------------------------------*/ /// +/// diff --git a/extensions/json-language-features/extension.webpack.config.js b/extensions/json-language-features/extension.webpack.config.js index 4c2ab99cf25..a4d4ff955d7 100644 --- a/extensions/json-language-features/extension.webpack.config.js +++ b/extensions/json-language-features/extension.webpack.config.js @@ -9,8 +9,9 @@ const withDefaults = require('../shared.webpack.config'); const path = require('path'); +var webpack = require('webpack'); -module.exports = withDefaults({ +const config = withDefaults({ context: path.join(__dirname, 'client'), entry: { extension: './src/jsonMain.ts', @@ -20,3 +21,8 @@ module.exports = withDefaults({ path: path.join(__dirname, 'client', 'dist') } }); + +// add plugin, don't replace inherited +config.plugins.push(new webpack.IgnorePlugin(/vertx/)); // request-light dependency + +module.exports = config; \ No newline at end of file diff --git a/extensions/json-language-features/package.json b/extensions/json-language-features/package.json index a1a5204c8b5..167583302c2 100644 --- a/extensions/json-language-features/package.json +++ b/extensions/json-language-features/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217", "engines": { "vscode": "0.10.x" @@ -14,6 +15,7 @@ "onLanguage:jsonc" ], "main": "./client/out/jsonMain", + "enableProposedApi": true, "scripts": { "compile": "gulp compile-extension:json-language-features-client compile-extension:json-language-features-server", "watch": "gulp watch-extension:json-language-features-client watch-extension:json-language-features-server", @@ -100,11 +102,12 @@ } }, "dependencies": { - "vscode-extension-telemetry": "0.1.0", - "vscode-languageclient": "^5.1.0", - "vscode-nls": "^4.0.0" + "request-light": "^0.2.4", + "vscode-extension-telemetry": "0.1.1", + "vscode-languageclient": "^5.3.0-next.6", + "vscode-nls": "^4.1.1" }, "devDependencies": { - "@types/node": "^8.10.25" + "@types/node": "^10.14.8" } } diff --git a/extensions/json-language-features/server/.npmignore b/extensions/json-language-features/server/.npmignore index a6661ddb7fc..3032fe8b26f 100644 --- a/extensions/json-language-features/server/.npmignore +++ b/extensions/json-language-features/server/.npmignore @@ -4,4 +4,7 @@ out/**/*.js.map src/ test/ tsconfig.json -.gitignore \ No newline at end of file +.gitignore +yarn.lock +extension.webpack.config.js +vscode-json-languageserver-*.tgz \ No newline at end of file diff --git a/extensions/json-language-features/server/README.md b/extensions/json-language-features/server/README.md index 27be5ab1bb1..5ca997d9e12 100644 --- a/extensions/json-language-features/server/README.md +++ b/extensions/json-language-features/server/README.md @@ -21,6 +21,8 @@ The server implements the following capabilities of the language server protocol - [Document Symbols](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol) for quick navigation to properties in the document. - [Document Colors](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentColor) for showing color decorators on values representing colors and [Color Presentation](https://microsoft.github.io/language-server-protocol/specification#textDocument_colorPresentation) for color presentation information to support color pickers. The location of colors is defined by the document's [JSON schema](http://json-schema.org/). All values marked with `"format": "color-hex"` (VSCode specific, non-standard JSON Schema extension) are considered color values. The supported color formats are `#rgb[a]` and `#rrggbb[aa]`. - [Code Formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_rangeFormatting) supporting ranges and formatting the whole document. +- [Folding Ranges](https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange) for all folding ranges in the document. +- Semantic Selection for semantic selection for one or multiple cursor positions. - [Diagnostics (Validation)](https://microsoft.github.io/language-server-protocol/specification#textDocument_publishDiagnostics) are pushed for all open documents - syntax errors - structural validation based on the document's [JSON schema](http://json-schema.org/). @@ -90,10 +92,39 @@ To find the schema for a given JSON document, the server uses the following mech - The settings define a schema association based on the documents URL. Settings can either associate a schema URL to a file or path pattern, and they can directly provide a schema. - Additionally, schema associations can also be provided by a custom 'schemaAssociations' configuration call. -Schemas are identified by URLs. To load the content of a schema, the JSON language server tries to load from that URL or path. The following URL schemas are supported: +Schemas are identified by URLs. To load the content of a schema, the JSON language server either tries to load from that URI or path itself, or delegates to the client. + +The `initializationOptions.handledSchemaProtocols` initialization option defines which URLs are handled by the server. Requests for all other URIs are send to the client. + +`handledSchemaProtocols` is part of the initialization options and can't be changed while the server is running. + +```ts +let clientOptions: LanguageClientOptions = { + initializationOptions: { + handledSchemaProtocols: ['file'] // language server should only try to load file URLs + } + ... +} +``` + +If `handledSchemaProtocols` is not set, the JSON language server will load the following URLs itself: + - `http`, `https`: Loaded using NodeJS's HTTP support. Proxies can be configured through the settings. - `file`: Loaded using NodeJS's `fs` support. -- `vscode`: Loaded by an LSP call to the client. + +#### Schema content request + +Requests for schemas with URLs not handled by the server are forwarded to the client through an LSP request. This request is a JSON language server specific, non-standardized, extension to the LSP. + +Request: +- method: 'vscode/content' +- params: `string` - The schema URL to request. +- response: `string` - The content of the schema with the given URL + +#### Schema content change notification + +When the client is aware that a schema content has changed, it will notify the server through a notification. This notification is a JSON language server specific, non-standardized, extension to the LSP. +The server will, as a response, clear the schema content from the cache and reload the schema content when required again. #### Schema associations notification @@ -111,20 +142,6 @@ interface ISchemaAssociations { - keys: a file names or file path (separated by `/`). `*` can be used as a wildcard. - values: An array of schema URLs -#### Schema content request - -The schema content for schema URLs that start with `vscode://` will be requested from the client through an LSP request. This request is a JSON language server specific, non-standardized, extension to the LSP. - -Request: -- method: 'vscode/content' -- params: `string` - The schema URL to request. The server will only ask for URLs that start with `vscode://` -- response: `string` - The content of the schema with the given URL - -#### Schema content change notification - -When the client is aware that a schema content has changed, it will notify the server through a notification. This notification is a JSON language server specific, non-standardized, extension to the LSP. -The server will, as a response, clear the schema content from the cache and reload the schema content when required again. - Notification: - method: 'json/schemaContent' - params: `string` the URL of the schema that has changed. @@ -154,7 +171,8 @@ To connect to the server from NodeJS, see Remy Suen's great write-up on [how to ## Participate -The source code of the JSON language server can be found [VSCode repository](https://github.com/Microsoft/vscode) at [extensions/json-language-features/server](https://github.com/Microsoft/vscode/tree/master/extensions/json-language-features/server). +The source code of the JSON language server can be found in the [VSCode repository](https://github.com/Microsoft/vscode) at [extensions/json-language-features/server](https://github.com/Microsoft/vscode/tree/master/extensions/json-language-features/server). + File issues and pull requests in the [VSCode GitHub Issues](https://github.com/Microsoft/vscode/issues). See the document [How to Contribute](https://github.com/Microsoft/vscode/wiki/How-to-Contribute) on how to build and run from source. Most of the functionality of the server is located in libraries: @@ -164,10 +182,12 @@ Most of the functionality of the server is located in libraries: Help on any of these projects is very welcome. -Please see also our [Code of Conduct](CODE_OF_CONDUCT.md). +## Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. ## License Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the [MIT](LICENSE.txt) License. +Licensed under the [MIT](https://github.com/microsoft/vscode/blob/master/LICENSE.txt) License. diff --git a/extensions/json-language-features/server/extension.webpack.config.js b/extensions/json-language-features/server/extension.webpack.config.js index b31abe55f25..22b23c1d94b 100644 --- a/extensions/json-language-features/server/extension.webpack.config.js +++ b/extensions/json-language-features/server/extension.webpack.config.js @@ -11,7 +11,7 @@ const withDefaults = require('../../shared.webpack.config'); const path = require('path'); var webpack = require('webpack'); -module.exports = withDefaults({ +const config = withDefaults({ context: path.join(__dirname), entry: { extension: './src/jsonServerMain.ts', @@ -19,12 +19,10 @@ module.exports = withDefaults({ output: { filename: 'jsonServerMain.js', path: path.join(__dirname, 'dist') - }, - plugins: [ - new webpack.NormalModuleReplacementPlugin( - /[/\\]vscode-languageserver[/\\]lib[/\\]files\.js/, - require.resolve('./build/filesFillIn') - ), - new webpack.IgnorePlugin(/vertx/) - ], + } }); + +// add plugin, don't replace inherited +config.plugins.push(new webpack.IgnorePlugin(/vertx/)); // request-light dependency + +module.exports = config; diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json index db0182fa088..bf5e3c8b09a 100644 --- a/extensions/json-language-features/server/package.json +++ b/extensions/json-language-features/server/package.json @@ -1,7 +1,7 @@ { "name": "vscode-json-languageserver", "description": "JSON language server", - "version": "1.0.1", + "version": "1.2.1", "author": "Microsoft Corporation", "license": "MIT", "engines": { @@ -12,22 +12,21 @@ }, "main": "./out/jsonServerMain", "dependencies": { - "jsonc-parser": "^2.0.2", + "jsonc-parser": "^2.1.0", "request-light": "^0.2.4", - "vscode-json-languageservice": "^3.2.1", - "vscode-languageserver": "^5.1.0", - "vscode-nls": "^4.0.0", - "vscode-uri": "^1.0.6" + "vscode-json-languageservice": "^3.3.1", + "vscode-languageserver": "^5.3.0-next.8", + "vscode-nls": "^4.1.1", + "vscode-uri": "^2.0.3" }, "devDependencies": { "@types/mocha": "2.2.33", - "@types/node": "^8.10.25" + "@types/node": "^10.14.8" }, "scripts": { - "prepublishOnly": "npm run clean && npm run test", - "preversion": "npm test", - "compile": "gulp compile-extension:json-language-features-server", - "watch": "gulp watch-extension:json-language-features-server", + "prepublishOnly": "npm run clean && npm run compile", + "compile": "npx gulp compile-extension:json-language-features-server", + "watch": "npx gulp watch-extension:json-language-features-server", "clean": "../../../node_modules/.bin/rimraf out", "install-service-next": "yarn add vscode-json-languageservice@next", "install-service-local": "yarn link vscode-json-languageservice", diff --git a/extensions/json-language-features/server/src/jsonServerMain.ts b/extensions/json-language-features/server/src/jsonServerMain.ts index e3b2dcb5f8f..ba1c7a18518 100644 --- a/extensions/json-language-features/server/src/jsonServerMain.ts +++ b/extensions/json-language-features/server/src/jsonServerMain.ts @@ -11,11 +11,10 @@ import { import { xhr, XHRResponse, configure as configureHttpRequests, getErrorStatusDescription } from 'request-light'; import * as fs from 'fs'; -import URI from 'vscode-uri'; +import { URI } from 'vscode-uri'; import * as URL from 'url'; -import { startsWith } from './utils/strings'; import { formatError, runSafe, runSafeAsync } from './utils/runner'; -import { JSONDocument, JSONSchema, getLanguageService, DocumentLanguageSettings, SchemaConfiguration } from 'vscode-json-languageservice'; +import { JSONDocument, JSONSchema, getLanguageService, DocumentLanguageSettings, SchemaConfiguration, ClientCapabilities } from 'vscode-json-languageservice'; import { getLanguageModelCache } from './languageModelCache'; interface ISchemaAssociations { @@ -57,53 +56,59 @@ const workspaceContext = { return URL.resolve(resource, relativePath); } }; +function getSchemaRequestService(handledSchemas: { [schema: string]: boolean }) { -const schemaRequestService = (uri: string): Thenable => { - if (startsWith(uri, 'file://')) { - const fsPath = URI.parse(uri).fsPath; - return new Promise((c, e) => { - fs.readFile(fsPath, 'UTF-8', (err, result) => { - err ? e(err.message || err.toString()) : c(result.toString()); - }); - }); - } else if (startsWith(uri, 'vscode://')) { + return (uri: string): Thenable => { + const protocol = uri.substr(0, uri.indexOf(':')); + + if (!handledSchemas || handledSchemas[protocol]) { + if (protocol === 'file') { + const fsPath = URI.parse(uri).fsPath; + return new Promise((c, e) => { + fs.readFile(fsPath, 'UTF-8', (err, result) => { + err ? e(err.message || err.toString()) : c(result.toString()); + }); + }); + } else if (protocol === 'http' || protocol === 'https') { + if (uri.indexOf('//schema.management.azure.com/') !== -1) { + /* __GDPR__ + "json.schema" : { + "schemaURL" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + connection.telemetry.logEvent({ + key: 'json.schema', + value: { + schemaURL: uri + } + }); + } + const headers = { 'Accept-Encoding': 'gzip, deflate' }; + return xhr({ url: uri, followRedirects: 5, headers }).then(response => { + return response.responseText; + }, (error: XHRResponse) => { + return Promise.reject(error.responseText || getErrorStatusDescription(error.status) || error.toString()); + }); + } + } return connection.sendRequest(VSCodeContentRequest.type, uri).then(responseText => { return responseText; }, error => { return Promise.reject(error.message); }); - } - if (uri.indexOf('//schema.management.azure.com/') !== -1) { - /* __GDPR__ - "json.schema" : { - "schemaURL" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - connection.telemetry.logEvent({ - key: 'json.schema', - value: { - schemaURL: uri - } - }); - } - const headers = { 'Accept-Encoding': 'gzip, deflate' }; - return xhr({ url: uri, followRedirects: 5, headers }).then(response => { - return response.responseText; - }, (error: XHRResponse) => { - return Promise.reject(error.responseText || getErrorStatusDescription(error.status) || error.toString()); - }); -}; + }; +} // create the JSON language service let languageService = getLanguageService({ - schemaRequestService, workspaceContext, contributions: [], + clientCapabilities: ClientCapabilities.LATEST }); -// Create a simple text document manager. The text document manager -// supports full document sync only +// Create a text document manager. const documents: TextDocuments = new TextDocuments(); + // Make the text document manager listen on the connection // for open, change and close text document events documents.listen(connection); @@ -117,8 +122,10 @@ let hierarchicalDocumentSymbolSupport = false; // in the passed params the rootPath of the workspace plus the client capabilities. connection.onInitialize((params: InitializeParams): InitializeResult => { + const handledProtocols = params.initializationOptions && params.initializationOptions['handledSchemaProtocols']; + languageService = getLanguageService({ - schemaRequestService, + schemaRequestService: getSchemaRequestService(handledProtocols), workspaceContext, contributions: [], clientCapabilities: params.capabilities @@ -148,7 +155,8 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { documentSymbolProvider: true, documentRangeFormattingProvider: false, colorProvider: {}, - foldingRangeProvider: true + foldingRangeProvider: true, + selectionRangeProvider: true }; return { capabilities }; @@ -427,5 +435,17 @@ connection.onFoldingRanges((params, token) => { }, null, `Error while computing folding ranges for ${params.textDocument.uri}`, token); }); + +connection.onSelectionRanges((params, token) => { + return runSafe(() => { + const document = documents.get(params.textDocument.uri); + if (document) { + const jsonDocument = getJSONDocument(document); + return languageService.getSelectionRanges(document, params.positions, jsonDocument); + } + return []; + }, [], `Error while computing selection ranges for ${params.textDocument.uri}`, token); +}); + // Listen on the connection connection.listen(); diff --git a/extensions/json-language-features/server/src/utils/strings.ts b/extensions/json-language-features/server/src/utils/strings.ts index 837f7238737..42a617f8a8a 100644 --- a/extensions/json-language-features/server/src/utils/strings.ts +++ b/extensions/json-language-features/server/src/utils/strings.ts @@ -3,20 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export function startsWith(haystack: string, needle: string): boolean { - if (haystack.length < needle.length) { - return false; - } - - for (let i = 0; i < needle.length; i++) { - if (haystack[i] !== needle[i]) { - return false; - } - } - - return true; -} - /** * Determines if haystack ends with needle. */ diff --git a/extensions/json-language-features/server/yarn.lock b/extensions/json-language-features/server/yarn.lock index 012e346360a..3bfcb75ac7d 100644 --- a/extensions/json-language-features/server/yarn.lock +++ b/extensions/json-language-features/server/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.33.tgz#d79a0061ec270379f4d9e225f4096fb436669def" integrity sha1-15oAYewnA3n02eIl9AlvtDZmne8= -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== agent-base@4, agent-base@^4.1.0: version "4.1.2" @@ -54,10 +54,10 @@ https-proxy-agent@^2.2.1: agent-base "^4.1.0" debug "^3.1.0" -jsonc-parser@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.0.2.tgz#42fcf56d70852a043fadafde51ddb4a85649978d" - integrity sha512-TSU435K5tEKh3g7bam1AFf+uZrISheoDsLlpmAo6wWZYqjsnd09lHYK1Qo+moK4Ikifev1Gdpa69g4NELKnCrQ== +jsonc-parser@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.1.0.tgz#eb0d0c7a3c33048524ce3574c57c7278fb2f1bf3" + integrity sha512-n9GrT8rrr2fhvBbANa1g+xFmgGK5X91KFeDwlKQ3+SJfmH5+tKv/M/kahx/TXOMflfWHKGKqKyfHQaLKTNzJ6w== ms@2.0.0: version "2.0.0" @@ -73,40 +73,41 @@ request-light@^0.2.4: https-proxy-agent "^2.2.1" vscode-nls "^4.0.0" -vscode-json-languageservice@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.2.1.tgz#991d51128ebd81c5525d0578cabfa5b03e3cba2a" - integrity sha512-ee9MJ70/xR55ywvm0bZsDLhA800HCRE27AYgMNTU14RSg20Y+ngHdQnUt6OmiTXrQDI/7sne6QUOtHIN0hPQYA== +vscode-json-languageservice@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.3.1.tgz#4ad2c82db849a7bbe54fcbf5c9b3a2ed26dc8fee" + integrity sha512-Qyvlrftexu1acvwbMt+CDehVrDZtFV1GAJrKdOCHQL9bWNhzI06KEiSd4iXR0NUOuAdroG/uU4wBkH6e5CcTXg== dependencies: - jsonc-parser "^2.0.2" - vscode-languageserver-types "^3.13.0" - vscode-nls "^4.0.0" - vscode-uri "^1.0.6" + jsonc-parser "^2.1.0" + vscode-languageserver-types "^3.15.0-next.2" + vscode-nls "^4.1.1" + vscode-uri "^2.0.3" -vscode-jsonrpc@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" - integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== +vscode-jsonrpc@^4.1.0-next.2: + version "4.1.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" + integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== -vscode-languageserver-protocol@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz#710d8e42119bb3affb1416e1e104bd6b4d503595" - integrity sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg== +vscode-languageserver-protocol@^3.15.0-next.6: + version "3.15.0-next.6" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" + integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== dependencies: - vscode-jsonrpc "^4.0.0" - vscode-languageserver-types "3.13.0" + vscode-jsonrpc "^4.1.0-next.2" + vscode-languageserver-types "^3.15.0-next.2" -vscode-languageserver-types@3.13.0, vscode-languageserver-types@^3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz#b704b024cef059f7b326611c99b9c8753c0a18b4" - integrity sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA== +vscode-languageserver-types@^3.15.0-next.2: + version "3.15.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" + integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== -vscode-languageserver@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.1.0.tgz#012a28f154cc7a848c443d217894942e4c3eeb39" - integrity sha512-CIsrgx2Y5VHS317g/HwkSTWYBIQmy0DwEyZPmB2pEpVOhYFwVsYpbiJwHIIyLQsQtmRaO4eA2xM8KPjNSdXpBw== +vscode-languageserver@^5.3.0-next.8: + version "5.3.0-next.8" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.3.0-next.8.tgz#12a4adf60374dbb93e153e08bdca5525f9b2029f" + integrity sha512-6vUb96wsRfrFqndril3gct/FBCSc24OxFZ2iz7kuEuXvLaIcEVOcSZIqQK8oFN7PdbAIaa9nnIpKSy4Yd15cIw== dependencies: - vscode-languageserver-protocol "3.13.0" + vscode-languageserver-protocol "^3.15.0-next.6" + vscode-textbuffer "^1.0.0" vscode-uri "^1.0.6" vscode-nls@^4.0.0: @@ -114,7 +115,22 @@ vscode-nls@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002" integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw== +vscode-nls@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" + integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== + +vscode-textbuffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/vscode-textbuffer/-/vscode-textbuffer-1.0.0.tgz#1faee638c8e0e4131c8d5c353993a1874acda086" + integrity sha512-zPaHo4urgpwsm+PrJWfNakolRpryNja18SUip/qIIsfhuEqEIPEXMxHOlFPjvDC4JgTaimkncNW7UMXRJTY6ow== + vscode-uri@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.6.tgz#6b8f141b0bbc44ad7b07e94f82f168ac7608ad4d" integrity sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww== + +vscode-uri@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543" + integrity sha512-4D3DI3F4uRy09WNtDGD93H9q034OHImxiIcSq664Hq1Y1AScehlP3qqZyTkX/RWxeu0MRMHGkrxYqm2qlDF/aw== diff --git a/extensions/json-language-features/yarn.lock b/extensions/json-language-features/yarn.lock index cfcbd4f4cbe..fdc89dd7cf1 100644 --- a/extensions/json-language-features/yarn.lock +++ b/extensions/json-language-features/yarn.lock @@ -2,20 +2,41 @@ # yarn lockfile v1 -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== -applicationinsights@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.6.tgz#bc201810de91cea910dab34e8ad35ecde488edeb" - integrity sha512-VQT3kBpJVPw5fCO5n+WUeSx0VHjxFtD7znYbILBlVgOS9/cMDuGFmV2Br3ObzFyZUDGNbEfW36fD1y2/vAiCKw== +agent-base@4, agent-base@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" + integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== + dependencies: + es6-promisify "^5.0.0" + +applicationinsights@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" + integrity sha512-KzOOGdphOS/lXWMFZe5440LUdFbrLpMvh2SaRxn7BmiI550KAoSb2gIhiq6kJZ9Ir3AxRRztjhzif+e5P5IXIg== dependencies: diagnostic-channel "0.2.0" diagnostic-channel-publishers "0.2.1" zone.js "0.7.6" +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + diagnostic-channel-publishers@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" @@ -28,6 +49,53 @@ diagnostic-channel@0.2.0: dependencies: semver "^5.3.0" +es6-promise@^4.0.3: + version "4.2.6" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f" + integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + +http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" + integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== + dependencies: + agent-base "4" + debug "3.1.0" + +https-proxy-agent@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" + integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ== + dependencies: + agent-base "^4.1.0" + debug "^3.1.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +request-light@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.4.tgz#3cea29c126682e6bcadf7915353322eeba01a755" + integrity sha512-pM9Fq5jRnSb+82V7M97rp8FE9/YNeP2L9eckB4Szd7lyeclSIx02aIpPO/6e4m6Dy31+FBN/zkFMTd2HkNO3ow== + dependencies: + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.1" + vscode-nls "^4.0.0" + semver@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" @@ -38,44 +106,49 @@ semver@^5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== -vscode-extension-telemetry@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.0.tgz#3cdcb61d03829966bd04b5f11471a1e40d6abaad" - integrity sha512-WVCnP+uLxlqB6UD98yQNV47mR5Rf79LFxpuZhSPhEf0Sb4tPZed3a63n003/dchhOwyCTCBuNN4n8XKJkLEI1Q== +vscode-extension-telemetry@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b" + integrity sha512-TkKKG/B/J94DP5qf6xWB4YaqlhWDg6zbbqVx7Bz//stLQNnfE9XS1xm3f6fl24c5+bnEK0/wHgMgZYKIKxPeUA== dependencies: - applicationinsights "1.0.6" + applicationinsights "1.0.8" -vscode-jsonrpc@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" - integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== +vscode-jsonrpc@^4.1.0-next.2: + version "4.1.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" + integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== -vscode-languageclient@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.1.0.tgz#650ab0dc9fd0daaade058a8471aaff5bc3f9580e" - integrity sha512-Z95Kps8UqD4o17HE3uCkZuvenOsxHVH46dKmaGVpGixEFZigPaVuVxLM/JWeIY9aRenoC0ZD9CK1O7L4jpffKg== +vscode-languageclient@^5.3.0-next.6: + version "5.3.0-next.6" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.3.0-next.6.tgz#35e74882781158e8b111911c0953869d3df08777" + integrity sha512-DxT8+gkenjCjJV6ArcP75/AQfx6HP6m6kHIbacPCpffMeoE1YMLKj6ZixA9J87yr0fMtBmqumLmDeGe7MIF2bw== dependencies: semver "^5.5.0" - vscode-languageserver-protocol "3.13.0" + vscode-languageserver-protocol "^3.15.0-next.6" -vscode-languageserver-protocol@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz#710d8e42119bb3affb1416e1e104bd6b4d503595" - integrity sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg== +vscode-languageserver-protocol@^3.15.0-next.6: + version "3.15.0-next.6" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" + integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== dependencies: - vscode-jsonrpc "^4.0.0" - vscode-languageserver-types "3.13.0" + vscode-jsonrpc "^4.1.0-next.2" + vscode-languageserver-types "^3.15.0-next.2" -vscode-languageserver-types@3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.13.0.tgz#b704b024cef059f7b326611c99b9c8753c0a18b4" - integrity sha512-BnJIxS+5+8UWiNKCP7W3g9FlE7fErFw0ofP5BXJe7c2tl0VeWh+nNHFbwAS2vmVC4a5kYxHBjRy0UeOtziemVA== +vscode-languageserver-types@^3.15.0-next.2: + version "3.15.0-next.2" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" + integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== vscode-nls@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002" integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw== +vscode-nls@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" + integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== + zone.js@0.7.6: version "0.7.6" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" diff --git a/extensions/json/cgmanifest.json b/extensions/json/cgmanifest.json index d0b23b7e064..fabb7a93aba 100644 --- a/extensions/json/cgmanifest.json +++ b/extensions/json/cgmanifest.json @@ -14,4 +14,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/json/package.json b/extensions/json/package.json index 517346cd347..1606f6a3d64 100644 --- a/extensions/json/package.json +++ b/extensions/json/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "0.10.x" }, @@ -23,12 +24,13 @@ ".bowerrc", ".jshintrc", ".jscsrc", - ".eslintrc", + ".swcrc", ".webmanifest", ".js.map", ".css.map" ], "filenames": [ + "composer.lock", ".watchmanconfig", ".ember-cli" ], @@ -46,7 +48,9 @@ "extensions": [ ".hintrc", ".babelrc", - ".jsonc" + ".jsonc", + ".eslintrc", + ".eslintrc.json" ], "configuration": "./language-configuration.json" } @@ -70,4 +74,4 @@ } ] } -} +} \ No newline at end of file diff --git a/extensions/less/package.json b/extensions/less/package.json index 20808a28527..4dea57de0f0 100644 --- a/extensions/less/package.json +++ b/extensions/less/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js atom/language-less grammars/less.cson ./syntaxes/less.tmLanguage.json" diff --git a/extensions/log/package.json b/extensions/log/package.json index 96fa29a0b30..c32f6320efa 100644 --- a/extensions/log/package.json +++ b/extensions/log/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, @@ -19,7 +20,7 @@ "*.log.?" ], "aliases": [ - "log" + "Log" ] } ], diff --git a/extensions/lua/cgmanifest.json b/extensions/lua/cgmanifest.json index 78d8538bf08..6cefc1ca59e 100644 --- a/extensions/lua/cgmanifest.json +++ b/extensions/lua/cgmanifest.json @@ -29,4 +29,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/lua/language-configuration.json b/extensions/lua/language-configuration.json index 73618cfe630..89e5c45b9ff 100644 --- a/extensions/lua/language-configuration.json +++ b/extensions/lua/language-configuration.json @@ -23,7 +23,7 @@ ["'", "'"] ], "indentationRules": { - "increaseIndentPattern": "((\\b(else|function|then|do|repeat)\\b((?!\\b(end|until)\\b).)*)|(\\{\\s*))$", + "increaseIndentPattern": "^((?!(\\-\\-)).)*((\\b(else|function|then|do|repeat)\\b((?!\\b(end|until)\\b).)*)|(\\{\\s*))$", "decreaseIndentPattern": "^\\s*((\\b(elseif|else|end|until)\\b)|(\\})|(\\)))" } } diff --git a/extensions/lua/package.json b/extensions/lua/package.json index e8504cd19d7..eda00f05f4f 100644 --- a/extensions/lua/package.json +++ b/extensions/lua/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js textmate/lua.tmbundle Syntaxes/Lua.plist ./syntaxes/lua.tmLanguage.json" diff --git a/extensions/make/cgmanifest.json b/extensions/make/cgmanifest.json index e575c65097b..c5a402aa39e 100644 --- a/extensions/make/cgmanifest.json +++ b/extensions/make/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "fadeevab/make.tmbundle", "repositoryUrl": "https://github.com/fadeevab/make.tmbundle", - "commitHash": "d01ce3404f9e2eed0fd4d07b5e24094c03599241" + "commitHash": "1b05209b483f81f42270bdda5514590e013e4896" } }, "licenseDetail": [ diff --git a/extensions/make/package.json b/extensions/make/package.json index f66762ba800..c5279e4cfdd 100644 --- a/extensions/make/package.json +++ b/extensions/make/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, diff --git a/extensions/make/syntaxes/make.tmLanguage.json b/extensions/make/syntaxes/make.tmLanguage.json index 79a3082a0bb..bdb08837c26 100644 --- a/extensions/make/syntaxes/make.tmLanguage.json +++ b/extensions/make/syntaxes/make.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/fadeevab/make.tmbundle/commit/d01ce3404f9e2eed0fd4d07b5e24094c03599241", + "version": "https://github.com/fadeevab/make.tmbundle/commit/1b05209b483f81f42270bdda5514590e013e4896", "name": "Makefile", "scopeName": "source.makefile", "patterns": [ @@ -132,6 +132,9 @@ }, { "include": "#comment" + }, + { + "include": "#directives" } ] }, @@ -320,7 +323,7 @@ ] }, "recipe": { - "begin": "^\\t([+-@]*)", + "begin": "^\\t([+\\-@]*)", "beginCaptures": { "1": { "name": "keyword.control.$1.makefile" @@ -342,7 +345,12 @@ "begin": "(^[ ]*|\\G\\s*)([^\\s]+)\\s*((?SwitchToPreview_16x \ No newline at end of file diff --git a/extensions/markdown-language-features/media/PreviewOnRightPane_16x.svg b/extensions/markdown-language-features/media/PreviewOnRightPane_16x.svg deleted file mode 100644 index 55778172a3b..00000000000 --- a/extensions/markdown-language-features/media/PreviewOnRightPane_16x.svg +++ /dev/null @@ -1 +0,0 @@ -PreviewInRightPanel_16x \ No newline at end of file diff --git a/extensions/markdown-language-features/media/PreviewOnRightPane_16x_dark.svg b/extensions/markdown-language-features/media/PreviewOnRightPane_16x_dark.svg deleted file mode 100644 index 390b2658bba..00000000000 --- a/extensions/markdown-language-features/media/PreviewOnRightPane_16x_dark.svg +++ /dev/null @@ -1 +0,0 @@ -PreviewInRightPanel_16x \ No newline at end of file diff --git a/extensions/markdown-language-features/media/Preview_inverse.svg b/extensions/markdown-language-features/media/Preview_inverse.svg deleted file mode 100644 index 1e7e89f7d48..00000000000 --- a/extensions/markdown-language-features/media/Preview_inverse.svg +++ /dev/null @@ -1 +0,0 @@ -SwitchToPreview_16x \ No newline at end of file diff --git a/extensions/markdown-language-features/media/ViewSource.svg b/extensions/markdown-language-features/media/ViewSource.svg deleted file mode 100644 index fccdf83d467..00000000000 --- a/extensions/markdown-language-features/media/ViewSource.svg +++ /dev/null @@ -1,3 +0,0 @@ - -]> \ No newline at end of file diff --git a/extensions/markdown-language-features/media/ViewSource_inverse.svg b/extensions/markdown-language-features/media/ViewSource_inverse.svg deleted file mode 100644 index f6302185aa4..00000000000 --- a/extensions/markdown-language-features/media/ViewSource_inverse.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extensions/markdown-language-features/media/index.js b/extensions/markdown-language-features/media/index.js index ede78807943..00afdf196af 100644 --- a/extensions/markdown-language-features/media/index.js +++ b/extensions/markdown-language-features/media/index.js @@ -643,12 +643,12 @@ const messaging_1 = __webpack_require__(/*! ./messaging */ "./preview-src/messag const scroll_sync_1 = __webpack_require__(/*! ./scroll-sync */ "./preview-src/scroll-sync.ts"); const settings_1 = __webpack_require__(/*! ./settings */ "./preview-src/settings.ts"); const throttle = __webpack_require__(/*! lodash.throttle */ "./node_modules/lodash.throttle/index.js"); -var scrollDisabled = true; +let scrollDisabled = true; const marker = new activeLineMarker_1.ActiveLineMarker(); const settings = settings_1.getSettings(); const vscode = acquireVsCodeApi(); // Set VS Code state -const state = settings_1.getData('data-state'); +let state = settings_1.getData('data-state'); vscode.setState(state); const messaging = messaging_1.createPosterForVsCode(vscode); window.cspAlerter.setPoster(messaging); @@ -741,8 +741,8 @@ document.addEventListener('click', event => { if (node.getAttribute('href').startsWith('#')) { break; } - if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:')) { - const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-resource:)/i, '').split('#'); + if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:') || node.href.startsWith(settings.webviewResourceRoot)) { + const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-resource:)/i, '').replace(new RegExp(`^${escapeRegExp(settings.webviewResourceRoot)}`)).split('#'); messaging.postMessage('clickLink', { path, fragment }); event.preventDefault(); event.stopPropagation(); @@ -762,10 +762,15 @@ if (settings.scrollEditorWithPreview) { const line = scroll_sync_1.getEditorLineNumberForPageOffset(window.scrollY); if (typeof line === 'number' && !isNaN(line)) { messaging.postMessage('revealLine', { line }); + state.line = line; + vscode.setState(state); } } }, 50)); } +function escapeRegExp(text) { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); +} /***/ }), @@ -825,11 +830,13 @@ const getCodeLineElements = (() => { let elements; return () => { if (!elements) { - elements = ([{ element: document.body, line: 0 }]).concat(Array.prototype.map.call(document.getElementsByClassName('code-line'), (element) => { + elements = [{ element: document.body, line: 0 }]; + for (const element of document.getElementsByClassName('code-line')) { const line = +element.getAttribute('data-line'); - return { element, line }; - }) - .filter((x) => !isNaN(x.line))); + if (!isNaN(line)) { + elements.push({ element: element, line }); + } + } } return elements; }; @@ -979,4 +986,4 @@ exports.getSettings = getSettings; /***/ }) /******/ }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2xvZGFzaC50aHJvdHRsZS9pbmRleC5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2FjdGl2ZUxpbmVNYXJrZXIudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvZXZlbnRzLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2luZGV4LnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL21lc3NhZ2luZy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zY3JvbGwtc3luYy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zZXR0aW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSx5REFBaUQsY0FBYztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBMkIsMEJBQTBCLEVBQUU7QUFDdkQseUNBQWlDLGVBQWU7QUFDaEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOERBQXNELCtEQUErRDs7QUFFckg7QUFDQTs7O0FBR0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLDhDQUE4QyxrQkFBa0I7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQsb0JBQW9CO0FBQ3ZFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsRUFBRTtBQUNiLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxFQUFFO0FBQ2IsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7Ozs7O0FDdGJBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNENBQTRDOztBQUU1Qzs7Ozs7Ozs7Ozs7Ozs7O0FDbkJBOzs7Z0dBR2dHO0FBQ2hHLCtGQUF5RDtBQUV6RDtJQUdDLDhCQUE4QixDQUFDLElBQVk7UUFDMUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLHNDQUF3QixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxJQUFJLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQsT0FBTyxDQUFDLE1BQStCO1FBQ3RDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDO0lBQ3hCLENBQUM7SUFFRCxvQkFBb0IsQ0FBQyxPQUFnQztRQUNwRCxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDZCxNQUFNLENBQUM7UUFDUixDQUFDO1FBQ0QsT0FBTyxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyx1QkFBdUIsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM1RSxDQUFDO0lBRUQsa0JBQWtCLENBQUMsT0FBZ0M7UUFDbEQsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ2QsTUFBTSxDQUFDO1FBQ1IsQ0FBQztRQUNELE9BQU8sQ0FBQyxTQUFTLElBQUksbUJBQW1CLENBQUM7SUFDMUMsQ0FBQztDQUNEO0FBM0JELDRDQTJCQzs7Ozs7Ozs7Ozs7Ozs7QUNqQ0Q7OztnR0FHZ0c7O0FBRWhHLDRCQUFtQyxDQUFhO0lBQy9DLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLEtBQUssU0FBUyxJQUFJLFFBQVEsQ0FBQyxVQUFVLEtBQUssZUFBZSxDQUFDLENBQUMsQ0FBQztRQUNsRixRQUFRLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUFDLElBQUksQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxFQUFFLENBQUM7SUFDTCxDQUFDO0FBQ0YsQ0FBQztBQU5ELGdEQU1DOzs7Ozs7Ozs7Ozs7OztBQ1hEOzs7Z0dBR2dHOztBQUVoRyw4R0FBc0Q7QUFDdEQsZ0ZBQThDO0FBQzlDLHlGQUFvRDtBQUNwRCwrRkFBMkY7QUFDM0Ysc0ZBQWtEO0FBQ2xELHVHQUE2QztBQUk3QyxJQUFJLGNBQWMsR0FBRyxJQUFJLENBQUM7QUFDMUIsTUFBTSxNQUFNLEdBQUcsSUFBSSxtQ0FBZ0IsRUFBRSxDQUFDO0FBQ3RDLE1BQU0sUUFBUSxHQUFHLHNCQUFXLEVBQUUsQ0FBQztBQUUvQixNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsRUFBRSxDQUFDO0FBRWxDLG9CQUFvQjtBQUNwQixNQUFNLEtBQUssR0FBRyxrQkFBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBQ3BDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7QUFFdkIsTUFBTSxTQUFTLEdBQUcsaUNBQXFCLENBQUMsTUFBTSxDQUFDLENBQUM7QUFFaEQsTUFBTSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUM7QUFDdkMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUVoRCxNQUFNLENBQUMsTUFBTSxHQUFHLEdBQUcsRUFBRTtJQUNwQixnQkFBZ0IsRUFBRSxDQUFDO0FBQ3BCLENBQUMsQ0FBQztBQUVGLDJCQUFrQixDQUFDLEdBQUcsRUFBRTtJQUN2QixFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxDQUFDO1FBQ3RDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZixNQUFNLFdBQVcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7WUFDbkMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUN6QixjQUFjLEdBQUcsSUFBSSxDQUFDO2dCQUN0QixzQ0FBd0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN2QyxDQUFDO1FBQ0YsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztBQUNGLENBQUMsQ0FBQyxDQUFDO0FBRUgsTUFBTSxZQUFZLEdBQUcsQ0FBQyxHQUFHLEVBQUU7SUFDMUIsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLENBQUMsSUFBWSxFQUFFLEVBQUU7UUFDMUMsY0FBYyxHQUFHLElBQUksQ0FBQztRQUN0QixzQ0FBd0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFUCxNQUFNLENBQUMsQ0FBQyxJQUFZLEVBQUUsUUFBYSxFQUFFLEVBQUU7UUFDdEMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2xCLFFBQVEsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1lBQ3JCLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoQixDQUFDO0lBQ0YsQ0FBQyxDQUFDO0FBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUVMLElBQUksZ0JBQWdCLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtJQUNwQyxNQUFNLFNBQVMsR0FBb0QsRUFBRSxDQUFDO0lBQ3RFLElBQUksTUFBTSxHQUFHLFFBQVEsQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNsRCxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ1osSUFBSSxDQUFDLENBQUM7UUFDTixHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDcEMsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRXRCLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdkMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDakMsQ0FBQztZQUVELFNBQVMsQ0FBQyxJQUFJLENBQUM7Z0JBQ2QsRUFBRSxFQUFFLEdBQUcsQ0FBQyxFQUFFO2dCQUNWLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTTtnQkFDbEIsS0FBSyxFQUFFLEdBQUcsQ0FBQyxLQUFLO2FBQ2hCLENBQUMsQ0FBQztRQUNKLENBQUM7UUFFRCxTQUFTLENBQUMsV0FBVyxDQUFDLGlCQUFpQixFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ3JELENBQUM7QUFDRixDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFFUCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRTtJQUN0QyxjQUFjLEdBQUcsSUFBSSxDQUFDO0lBQ3RCLGdCQUFnQixFQUFFLENBQUM7QUFDcEIsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBRVQsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsRUFBRTtJQUMxQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUMzQyxNQUFNLENBQUM7SUFDUixDQUFDO0lBRUQsTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3pCLEtBQUssZ0NBQWdDO1lBQ3BDLE1BQU0sQ0FBQyw4QkFBOEIsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3ZELEtBQUssQ0FBQztRQUVQLEtBQUssWUFBWTtZQUNoQixZQUFZLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDeEMsS0FBSyxDQUFDO0lBQ1IsQ0FBQztBQUNGLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUVWLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDLEVBQUU7SUFDN0MsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsMkJBQTJCLENBQUMsQ0FBQyxDQUFDO1FBQzNDLE1BQU0sQ0FBQztJQUNSLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsR0FBRyxDQUFDLENBQUMsSUFBSSxJQUFJLEdBQUcsS0FBSyxDQUFDLE1BQXFCLEVBQUUsSUFBSSxFQUFFLElBQUksR0FBRyxJQUFJLENBQUMsVUFBeUIsRUFBRSxDQUFDO1FBQzFGLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQztZQUMxQixNQUFNLENBQUM7UUFDUixDQUFDO0lBQ0YsQ0FBQztJQUVELE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7SUFDM0IsTUFBTSxJQUFJLEdBQUcsOENBQWdDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEQsRUFBRSxDQUFDLENBQUMsT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxTQUFTLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMvRCxDQUFDO0FBQ0YsQ0FBQyxDQUFDLENBQUM7QUFFSCxRQUFRLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxFQUFFO0lBQzFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNaLE1BQU0sQ0FBQztJQUNSLENBQUM7SUFFRCxJQUFJLElBQUksR0FBUSxLQUFLLENBQUMsTUFBTSxDQUFDO0lBQzdCLE9BQU8sSUFBSSxFQUFFLENBQUM7UUFDYixFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxPQUFPLEtBQUssR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3ZELEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDL0MsS0FBSyxDQUFDO1lBQ1AsQ0FBQztZQUNELEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNqRixNQUFNLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGdDQUFnQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDNUYsU0FBUyxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztnQkFDdkQsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUN2QixLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQ3hCLEtBQUssQ0FBQztZQUNQLENBQUM7WUFDRCxLQUFLLENBQUM7UUFDUCxDQUFDO1FBQ0QsSUFBSSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDeEIsQ0FBQztBQUNGLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUVULEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLENBQUM7SUFDdEMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsR0FBRyxFQUFFO1FBQy9DLEVBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7WUFDcEIsY0FBYyxHQUFHLEtBQUssQ0FBQztRQUN4QixDQUFDO1FBQUMsSUFBSSxDQUFDLENBQUM7WUFDUCxNQUFNLElBQUksR0FBRyw4Q0FBZ0MsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDOUQsRUFBRSxDQUFDLENBQUMsT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDOUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxZQUFZLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQy9DLENBQUM7UUFDRixDQUFDO0lBQ0YsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDVCxDQUFDOzs7Ozs7Ozs7Ozs7OztBQzdKRDs7O2dHQUdnRzs7QUFFaEcsc0ZBQXlDO0FBUzVCLDZCQUFxQixHQUFHLENBQUMsTUFBVyxFQUFFLEVBQUU7SUFDcEQsTUFBTSxDQUFDLElBQUk7UUFDVixXQUFXLENBQUMsSUFBWSxFQUFFLElBQVk7WUFDckMsTUFBTSxDQUFDLFdBQVcsQ0FBQztnQkFDbEIsSUFBSTtnQkFDSixNQUFNLEVBQUUsc0JBQVcsRUFBRSxDQUFDLE1BQU07Z0JBQzVCLElBQUk7YUFDSixDQUFDLENBQUM7UUFDSixDQUFDO0tBQ0QsQ0FBQztBQUNILENBQUMsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7QUN4QkY7OztnR0FHZ0c7O0FBRWhHLHNGQUF5QztBQUd6QyxlQUFlLEdBQVcsRUFBRSxHQUFXLEVBQUUsS0FBYTtJQUNyRCxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUM1QyxDQUFDO0FBRUQsbUJBQW1CLElBQVk7SUFDOUIsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsc0JBQVcsRUFBRSxDQUFDLFNBQVMsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDcEQsQ0FBQztBQVFELE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxHQUFHLEVBQUU7SUFDakMsSUFBSSxRQUEyQixDQUFDO0lBQ2hDLE1BQU0sQ0FBQyxHQUFHLEVBQUU7UUFDWCxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDZixRQUFRLEdBQUcsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUNqRixRQUFRLENBQUMsc0JBQXNCLENBQUMsV0FBVyxDQUFDLEVBQzVDLENBQUMsT0FBWSxFQUFFLEVBQUU7Z0JBQ2hCLE1BQU0sSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDaEQsTUFBTSxDQUFDLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDO1lBQzFCLENBQUMsQ0FBQztpQkFDRCxNQUFNLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkMsQ0FBQztRQUNELE1BQU0sQ0FBQyxRQUFRLENBQUM7SUFDakIsQ0FBQyxDQUFDO0FBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUVMOzs7OztHQUtHO0FBQ0gsa0NBQXlDLFVBQWtCO0lBQzFELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDMUMsTUFBTSxLQUFLLEdBQUcsbUJBQW1CLEVBQUUsQ0FBQztJQUNwQyxJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDO0lBQ2hDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sS0FBSyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDM0IsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBQy9CLE1BQU0sQ0FBQyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDO1FBQzdDLENBQUM7UUFBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBQ3BDLE1BQU0sQ0FBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDbEMsQ0FBQztRQUNELFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDbEIsQ0FBQztJQUNELE1BQU0sQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDO0FBQ3JCLENBQUM7QUFiRCw0REFhQztBQUVEOztHQUVHO0FBQ0gscUNBQTRDLE1BQWM7SUFDekQsTUFBTSxLQUFLLEdBQUcsbUJBQW1CLEVBQUUsQ0FBQztJQUNwQyxNQUFNLFFBQVEsR0FBRyxNQUFNLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQztJQUN6QyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNaLElBQUksRUFBRSxHQUFHLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQzFCLE9BQU8sRUFBRSxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQztRQUNwQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3RDLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUMxRCxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQyxNQUFNLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQztZQUM1QyxFQUFFLEdBQUcsR0FBRyxDQUFDO1FBQ1YsQ0FBQztRQUNELElBQUksQ0FBQyxDQUFDO1lBQ0wsRUFBRSxHQUFHLEdBQUcsQ0FBQztRQUNWLENBQUM7SUFDRixDQUFDO0lBQ0QsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzVCLE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMscUJBQXFCLEVBQUUsQ0FBQztJQUMzRCxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxJQUFJLFFBQVEsQ0FBQyxHQUFHLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUN4QyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUIsTUFBTSxDQUFDLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUM7SUFDakQsQ0FBQztJQUNELE1BQU0sQ0FBQyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsQ0FBQztBQUNoQyxDQUFDO0FBdEJELGtFQXNCQztBQUVEOztHQUVHO0FBQ0gsa0NBQXlDLElBQVk7SUFDcEQsRUFBRSxDQUFDLENBQUMsQ0FBQyxzQkFBVyxFQUFFLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxDQUFDO1FBQzVDLE1BQU0sQ0FBQztJQUNSLENBQUM7SUFFRCxFQUFFLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNmLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNqQyxNQUFNLENBQUM7SUFDUixDQUFDO0lBRUQsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsR0FBRyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxRCxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDZixNQUFNLENBQUM7SUFDUixDQUFDO0lBQ0QsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDO0lBQ2pCLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMscUJBQXFCLEVBQUUsQ0FBQztJQUN0RCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBQzdCLEVBQUUsQ0FBQyxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3pDLDhEQUE4RDtRQUM5RCxNQUFNLGVBQWUsR0FBRyxDQUFDLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3RSxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFLENBQUMsR0FBRyxHQUFHLFdBQVcsQ0FBQztRQUM3RSxRQUFRLEdBQUcsV0FBVyxHQUFHLGVBQWUsR0FBRyxhQUFhLENBQUM7SUFDMUQsQ0FBQztJQUFDLElBQUksQ0FBQyxDQUFDO1FBQ1AsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsRCxRQUFRLEdBQUcsV0FBVyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxpQkFBaUIsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFDRCxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDO0FBQ3ZFLENBQUM7QUEzQkQsNERBMkJDO0FBRUQsMENBQWlELE1BQWM7SUFDOUQsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsR0FBRywyQkFBMkIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMvRCxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ2QsTUFBTSxjQUFjLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQ2hFLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE9BQU8sR0FBRyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDMUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNWLE1BQU0sdUJBQXVCLEdBQUcsa0JBQWtCLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFLENBQUMsR0FBRyxHQUFHLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNySCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxHQUFHLHVCQUF1QixHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkYsTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4QixDQUFDO1FBQ0QsSUFBSSxDQUFDLENBQUM7WUFDTCxNQUFNLHFCQUFxQixHQUFHLGtCQUFrQixHQUFHLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzNFLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxJQUFJLEdBQUcscUJBQXFCLENBQUM7WUFDbkQsTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4QixDQUFDO0lBQ0YsQ0FBQztJQUNELE1BQU0sQ0FBQyxJQUFJLENBQUM7QUFDYixDQUFDO0FBakJELDRFQWlCQzs7Ozs7Ozs7Ozs7Ozs7QUN2SUQ7OztnR0FHZ0c7O0FBWWhHLElBQUksY0FBYyxHQUFnQyxTQUFTLENBQUM7QUFFNUQsaUJBQXdCLEdBQVc7SUFDbEMsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO0lBQ3hFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDYixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDVixNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QixDQUFDO0lBQ0YsQ0FBQztJQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLEdBQUcsRUFBRSxDQUFDLENBQUM7QUFDbkQsQ0FBQztBQVZELDBCQVVDO0FBRUQ7SUFDQyxFQUFFLENBQUMsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxjQUFjLENBQUM7SUFDdkIsQ0FBQztJQUVELGNBQWMsR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDMUMsRUFBRSxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztRQUNwQixNQUFNLENBQUMsY0FBYyxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixDQUFDLENBQUM7QUFDNUMsQ0FBQztBQVhELGtDQVdDIiwiZmlsZSI6ImluZGV4LmpzIiwic291cmNlc0NvbnRlbnQiOlsiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbiBcdFx0XHRyZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcbiBcdFx0fVxuIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gXHRcdFx0aTogbW9kdWxlSWQsXG4gXHRcdFx0bDogZmFsc2UsXG4gXHRcdFx0ZXhwb3J0czoge31cbiBcdFx0fTtcblxuIFx0XHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cbiBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbiBcdFx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuIFx0XHRtb2R1bGUubCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gZGVmaW5lIGdldHRlciBmdW5jdGlvbiBmb3IgaGFybW9ueSBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiBcdFx0aWYoIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSkge1xuIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7XG4gXHRcdFx0XHRjb25maWd1cmFibGU6IGZhbHNlLFxuIFx0XHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcbiBcdFx0XHRcdGdldDogZ2V0dGVyXG4gXHRcdFx0fSk7XG4gXHRcdH1cbiBcdH07XG5cbiBcdC8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uciA9IGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiBcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbiBcdH07XG5cbiBcdC8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiBcdFx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHsgcmV0dXJuIG1vZHVsZVsnZGVmYXVsdCddOyB9IDpcbiBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCAnYScsIGdldHRlcik7XG4gXHRcdHJldHVybiBnZXR0ZXI7XG4gXHR9O1xuXG4gXHQvLyBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGxcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cblxuIFx0Ly8gTG9hZCBlbnRyeSBtb2R1bGUgYW5kIHJldHVybiBleHBvcnRzXG4gXHRyZXR1cm4gX193ZWJwYWNrX3JlcXVpcmVfXyhfX3dlYnBhY2tfcmVxdWlyZV9fLnMgPSBcIi4vcHJldmlldy1zcmMvaW5kZXgudHNcIik7XG4iLCIvKipcbiAqIGxvZGFzaCAoQ3VzdG9tIEJ1aWxkKSA8aHR0cHM6Ly9sb2Rhc2guY29tLz5cbiAqIEJ1aWxkOiBgbG9kYXNoIG1vZHVsYXJpemUgZXhwb3J0cz1cIm5wbVwiIC1vIC4vYFxuICogQ29weXJpZ2h0IGpRdWVyeSBGb3VuZGF0aW9uIGFuZCBvdGhlciBjb250cmlidXRvcnMgPGh0dHBzOi8vanF1ZXJ5Lm9yZy8+XG4gKiBSZWxlYXNlZCB1bmRlciBNSVQgbGljZW5zZSA8aHR0cHM6Ly9sb2Rhc2guY29tL2xpY2Vuc2U+XG4gKiBCYXNlZCBvbiBVbmRlcnNjb3JlLmpzIDEuOC4zIDxodHRwOi8vdW5kZXJzY29yZWpzLm9yZy9MSUNFTlNFPlxuICogQ29weXJpZ2h0IEplcmVteSBBc2hrZW5hcywgRG9jdW1lbnRDbG91ZCBhbmQgSW52ZXN0aWdhdGl2ZSBSZXBvcnRlcnMgJiBFZGl0b3JzXG4gKi9cblxuLyoqIFVzZWQgYXMgdGhlIGBUeXBlRXJyb3JgIG1lc3NhZ2UgZm9yIFwiRnVuY3Rpb25zXCIgbWV0aG9kcy4gKi9cbnZhciBGVU5DX0VSUk9SX1RFWFQgPSAnRXhwZWN0ZWQgYSBmdW5jdGlvbic7XG5cbi8qKiBVc2VkIGFzIHJlZmVyZW5jZXMgZm9yIHZhcmlvdXMgYE51bWJlcmAgY29uc3RhbnRzLiAqL1xudmFyIE5BTiA9IDAgLyAwO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgc3ltYm9sVGFnID0gJ1tvYmplY3QgU3ltYm9sXSc7XG5cbi8qKiBVc2VkIHRvIG1hdGNoIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlc3BhY2UuICovXG52YXIgcmVUcmltID0gL15cXHMrfFxccyskL2c7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBiYWQgc2lnbmVkIGhleGFkZWNpbWFsIHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc0JhZEhleCA9IC9eWy0rXTB4WzAtOWEtZl0rJC9pO1xuXG4vKiogVXNlZCB0byBkZXRlY3QgYmluYXJ5IHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc0JpbmFyeSA9IC9eMGJbMDFdKyQvaTtcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IG9jdGFsIHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVJc09jdGFsID0gL14wb1swLTddKyQvaTtcblxuLyoqIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHdpdGhvdXQgYSBkZXBlbmRlbmN5IG9uIGByb290YC4gKi9cbnZhciBmcmVlUGFyc2VJbnQgPSBwYXJzZUludDtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcy4gKi9cbnZhciBmcmVlR2xvYmFsID0gdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWwgJiYgZ2xvYmFsLk9iamVjdCA9PT0gT2JqZWN0ICYmIGdsb2JhbDtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBzZWxmYC4gKi9cbnZhciBmcmVlU2VsZiA9IHR5cGVvZiBzZWxmID09ICdvYmplY3QnICYmIHNlbGYgJiYgc2VsZi5PYmplY3QgPT09IE9iamVjdCAmJiBzZWxmO1xuXG4vKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbnZhciByb290ID0gZnJlZUdsb2JhbCB8fCBmcmVlU2VsZiB8fCBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuXG4vKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKipcbiAqIFVzZWQgdG8gcmVzb2x2ZSB0aGVcbiAqIFtgdG9TdHJpbmdUYWdgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nKVxuICogb2YgdmFsdWVzLlxuICovXG52YXIgb2JqZWN0VG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xudmFyIG5hdGl2ZU1heCA9IE1hdGgubWF4LFxuICAgIG5hdGl2ZU1pbiA9IE1hdGgubWluO1xuXG4vKipcbiAqIEdldHMgdGhlIHRpbWVzdGFtcCBvZiB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0aGF0IGhhdmUgZWxhcHNlZCBzaW5jZVxuICogdGhlIFVuaXggZXBvY2ggKDEgSmFudWFyeSAxOTcwIDAwOjAwOjAwIFVUQykuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAyLjQuMFxuICogQGNhdGVnb3J5IERhdGVcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHRpbWVzdGFtcC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5kZWZlcihmdW5jdGlvbihzdGFtcCkge1xuICogICBjb25zb2xlLmxvZyhfLm5vdygpIC0gc3RhbXApO1xuICogfSwgXy5ub3coKSk7XG4gKiAvLyA9PiBMb2dzIHRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIGl0IHRvb2sgZm9yIHRoZSBkZWZlcnJlZCBpbnZvY2F0aW9uLlxuICovXG52YXIgbm93ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiByb290LkRhdGUubm93KCk7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBkZWJvdW5jZWQgZnVuY3Rpb24gdGhhdCBkZWxheXMgaW52b2tpbmcgYGZ1bmNgIHVudGlsIGFmdGVyIGB3YWl0YFxuICogbWlsbGlzZWNvbmRzIGhhdmUgZWxhcHNlZCBzaW5jZSB0aGUgbGFzdCB0aW1lIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gd2FzXG4gKiBpbnZva2VkLiBUaGUgZGVib3VuY2VkIGZ1bmN0aW9uIGNvbWVzIHdpdGggYSBgY2FuY2VsYCBtZXRob2QgdG8gY2FuY2VsXG4gKiBkZWxheWVkIGBmdW5jYCBpbnZvY2F0aW9ucyBhbmQgYSBgZmx1c2hgIG1ldGhvZCB0byBpbW1lZGlhdGVseSBpbnZva2UgdGhlbS5cbiAqIFByb3ZpZGUgYG9wdGlvbnNgIHRvIGluZGljYXRlIHdoZXRoZXIgYGZ1bmNgIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZVxuICogbGVhZGluZyBhbmQvb3IgdHJhaWxpbmcgZWRnZSBvZiB0aGUgYHdhaXRgIHRpbWVvdXQuIFRoZSBgZnVuY2AgaXMgaW52b2tlZFxuICogd2l0aCB0aGUgbGFzdCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbi4gU3Vic2VxdWVudFxuICogY2FsbHMgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2BcbiAqIGludm9jYXRpb24uXG4gKlxuICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpc1xuICogaW52b2tlZCBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dCBvbmx5IGlmIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb25cbiAqIGlzIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAqXG4gKiBJZiBgd2FpdGAgaXMgYDBgIGFuZCBgbGVhZGluZ2AgaXMgYGZhbHNlYCwgYGZ1bmNgIGludm9jYXRpb24gaXMgZGVmZXJyZWRcbiAqIHVudGlsIHRvIHRoZSBuZXh0IHRpY2ssIHNpbWlsYXIgdG8gYHNldFRpbWVvdXRgIHdpdGggYSB0aW1lb3V0IG9mIGAwYC5cbiAqXG4gKiBTZWUgW0RhdmlkIENvcmJhY2hvJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9jc3MtdHJpY2tzLmNvbS9kZWJvdW5jaW5nLXRocm90dGxpbmctZXhwbGFpbmVkLWV4YW1wbGVzLylcbiAqIGZvciBkZXRhaWxzIG92ZXIgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYF8uZGVib3VuY2VgIGFuZCBgXy50aHJvdHRsZWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBkZWJvdW5jZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPWZhbHNlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5tYXhXYWl0XVxuICogIFRoZSBtYXhpbXVtIHRpbWUgYGZ1bmNgIGlzIGFsbG93ZWQgdG8gYmUgZGVsYXllZCBiZWZvcmUgaXQncyBpbnZva2VkLlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy50cmFpbGluZz10cnVlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBkZWJvdW5jZWQgZnVuY3Rpb24uXG4gKiBAZXhhbXBsZVxuICpcbiAqIC8vIEF2b2lkIGNvc3RseSBjYWxjdWxhdGlvbnMgd2hpbGUgdGhlIHdpbmRvdyBzaXplIGlzIGluIGZsdXguXG4gKiBqUXVlcnkod2luZG93KS5vbigncmVzaXplJywgXy5kZWJvdW5jZShjYWxjdWxhdGVMYXlvdXQsIDE1MCkpO1xuICpcbiAqIC8vIEludm9rZSBgc2VuZE1haWxgIHdoZW4gY2xpY2tlZCwgZGVib3VuY2luZyBzdWJzZXF1ZW50IGNhbGxzLlxuICogalF1ZXJ5KGVsZW1lbnQpLm9uKCdjbGljaycsIF8uZGVib3VuY2Uoc2VuZE1haWwsIDMwMCwge1xuICogICAnbGVhZGluZyc6IHRydWUsXG4gKiAgICd0cmFpbGluZyc6IGZhbHNlXG4gKiB9KSk7XG4gKlxuICogLy8gRW5zdXJlIGBiYXRjaExvZ2AgaXMgaW52b2tlZCBvbmNlIGFmdGVyIDEgc2Vjb25kIG9mIGRlYm91bmNlZCBjYWxscy5cbiAqIHZhciBkZWJvdW5jZWQgPSBfLmRlYm91bmNlKGJhdGNoTG9nLCAyNTAsIHsgJ21heFdhaXQnOiAxMDAwIH0pO1xuICogdmFyIHNvdXJjZSA9IG5ldyBFdmVudFNvdXJjZSgnL3N0cmVhbScpO1xuICogalF1ZXJ5KHNvdXJjZSkub24oJ21lc3NhZ2UnLCBkZWJvdW5jZWQpO1xuICpcbiAqIC8vIENhbmNlbCB0aGUgdHJhaWxpbmcgZGVib3VuY2VkIGludm9jYXRpb24uXG4gKiBqUXVlcnkod2luZG93KS5vbigncG9wc3RhdGUnLCBkZWJvdW5jZWQuY2FuY2VsKTtcbiAqL1xuZnVuY3Rpb24gZGVib3VuY2UoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICB2YXIgbGFzdEFyZ3MsXG4gICAgICBsYXN0VGhpcyxcbiAgICAgIG1heFdhaXQsXG4gICAgICByZXN1bHQsXG4gICAgICB0aW1lcklkLFxuICAgICAgbGFzdENhbGxUaW1lLFxuICAgICAgbGFzdEludm9rZVRpbWUgPSAwLFxuICAgICAgbGVhZGluZyA9IGZhbHNlLFxuICAgICAgbWF4aW5nID0gZmFsc2UsXG4gICAgICB0cmFpbGluZyA9IHRydWU7XG5cbiAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gIH1cbiAgd2FpdCA9IHRvTnVtYmVyKHdhaXQpIHx8IDA7XG4gIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgIGxlYWRpbmcgPSAhIW9wdGlvbnMubGVhZGluZztcbiAgICBtYXhpbmcgPSAnbWF4V2FpdCcgaW4gb3B0aW9ucztcbiAgICBtYXhXYWl0ID0gbWF4aW5nID8gbmF0aXZlTWF4KHRvTnVtYmVyKG9wdGlvbnMubWF4V2FpdCkgfHwgMCwgd2FpdCkgOiBtYXhXYWl0O1xuICAgIHRyYWlsaW5nID0gJ3RyYWlsaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLnRyYWlsaW5nIDogdHJhaWxpbmc7XG4gIH1cblxuICBmdW5jdGlvbiBpbnZva2VGdW5jKHRpbWUpIHtcbiAgICB2YXIgYXJncyA9IGxhc3RBcmdzLFxuICAgICAgICB0aGlzQXJnID0gbGFzdFRoaXM7XG5cbiAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkO1xuICAgIGxhc3RJbnZva2VUaW1lID0gdGltZTtcbiAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBsZWFkaW5nRWRnZSh0aW1lKSB7XG4gICAgLy8gUmVzZXQgYW55IGBtYXhXYWl0YCB0aW1lci5cbiAgICBsYXN0SW52b2tlVGltZSA9IHRpbWU7XG4gICAgLy8gU3RhcnQgdGhlIHRpbWVyIGZvciB0aGUgdHJhaWxpbmcgZWRnZS5cbiAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgIC8vIEludm9rZSB0aGUgbGVhZGluZyBlZGdlLlxuICAgIHJldHVybiBsZWFkaW5nID8gaW52b2tlRnVuYyh0aW1lKSA6IHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbWFpbmluZ1dhaXQodGltZSkge1xuICAgIHZhciB0aW1lU2luY2VMYXN0Q2FsbCA9IHRpbWUgLSBsYXN0Q2FsbFRpbWUsXG4gICAgICAgIHRpbWVTaW5jZUxhc3RJbnZva2UgPSB0aW1lIC0gbGFzdEludm9rZVRpbWUsXG4gICAgICAgIHJlc3VsdCA9IHdhaXQgLSB0aW1lU2luY2VMYXN0Q2FsbDtcblxuICAgIHJldHVybiBtYXhpbmcgPyBuYXRpdmVNaW4ocmVzdWx0LCBtYXhXYWl0IC0gdGltZVNpbmNlTGFzdEludm9rZSkgOiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBzaG91bGRJbnZva2UodGltZSkge1xuICAgIHZhciB0aW1lU2luY2VMYXN0Q2FsbCA9IHRpbWUgLSBsYXN0Q2FsbFRpbWUsXG4gICAgICAgIHRpbWVTaW5jZUxhc3RJbnZva2UgPSB0aW1lIC0gbGFzdEludm9rZVRpbWU7XG5cbiAgICAvLyBFaXRoZXIgdGhpcyBpcyB0aGUgZmlyc3QgY2FsbCwgYWN0aXZpdHkgaGFzIHN0b3BwZWQgYW5kIHdlJ3JlIGF0IHRoZVxuICAgIC8vIHRyYWlsaW5nIGVkZ2UsIHRoZSBzeXN0ZW0gdGltZSBoYXMgZ29uZSBiYWNrd2FyZHMgYW5kIHdlJ3JlIHRyZWF0aW5nXG4gICAgLy8gaXQgYXMgdGhlIHRyYWlsaW5nIGVkZ2UsIG9yIHdlJ3ZlIGhpdCB0aGUgYG1heFdhaXRgIGxpbWl0LlxuICAgIHJldHVybiAobGFzdENhbGxUaW1lID09PSB1bmRlZmluZWQgfHwgKHRpbWVTaW5jZUxhc3RDYWxsID49IHdhaXQpIHx8XG4gICAgICAodGltZVNpbmNlTGFzdENhbGwgPCAwKSB8fCAobWF4aW5nICYmIHRpbWVTaW5jZUxhc3RJbnZva2UgPj0gbWF4V2FpdCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gdGltZXJFeHBpcmVkKCkge1xuICAgIHZhciB0aW1lID0gbm93KCk7XG4gICAgaWYgKHNob3VsZEludm9rZSh0aW1lKSkge1xuICAgICAgcmV0dXJuIHRyYWlsaW5nRWRnZSh0aW1lKTtcbiAgICB9XG4gICAgLy8gUmVzdGFydCB0aGUgdGltZXIuXG4gICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCByZW1haW5pbmdXYWl0KHRpbWUpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRyYWlsaW5nRWRnZSh0aW1lKSB7XG4gICAgdGltZXJJZCA9IHVuZGVmaW5lZDtcblxuICAgIC8vIE9ubHkgaW52b2tlIGlmIHdlIGhhdmUgYGxhc3RBcmdzYCB3aGljaCBtZWFucyBgZnVuY2AgaGFzIGJlZW5cbiAgICAvLyBkZWJvdW5jZWQgYXQgbGVhc3Qgb25jZS5cbiAgICBpZiAodHJhaWxpbmcgJiYgbGFzdEFyZ3MpIHtcbiAgICAgIHJldHVybiBpbnZva2VGdW5jKHRpbWUpO1xuICAgIH1cbiAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBjYW5jZWwoKSB7XG4gICAgaWYgKHRpbWVySWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVySWQpO1xuICAgIH1cbiAgICBsYXN0SW52b2tlVGltZSA9IDA7XG4gICAgbGFzdEFyZ3MgPSBsYXN0Q2FsbFRpbWUgPSBsYXN0VGhpcyA9IHRpbWVySWQgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBmdW5jdGlvbiBmbHVzaCgpIHtcbiAgICByZXR1cm4gdGltZXJJZCA9PT0gdW5kZWZpbmVkID8gcmVzdWx0IDogdHJhaWxpbmdFZGdlKG5vdygpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlYm91bmNlZCgpIHtcbiAgICB2YXIgdGltZSA9IG5vdygpLFxuICAgICAgICBpc0ludm9raW5nID0gc2hvdWxkSW52b2tlKHRpbWUpO1xuXG4gICAgbGFzdEFyZ3MgPSBhcmd1bWVudHM7XG4gICAgbGFzdFRoaXMgPSB0aGlzO1xuICAgIGxhc3RDYWxsVGltZSA9IHRpbWU7XG5cbiAgICBpZiAoaXNJbnZva2luZykge1xuICAgICAgaWYgKHRpbWVySWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gbGVhZGluZ0VkZ2UobGFzdENhbGxUaW1lKTtcbiAgICAgIH1cbiAgICAgIGlmIChtYXhpbmcpIHtcbiAgICAgICAgLy8gSGFuZGxlIGludm9jYXRpb25zIGluIGEgdGlnaHQgbG9vcC5cbiAgICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICAgICAgcmV0dXJuIGludm9rZUZ1bmMobGFzdENhbGxUaW1lKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRpbWVySWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICBkZWJvdW5jZWQuY2FuY2VsID0gY2FuY2VsO1xuICBkZWJvdW5jZWQuZmx1c2ggPSBmbHVzaDtcbiAgcmV0dXJuIGRlYm91bmNlZDtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgdGhyb3R0bGVkIGZ1bmN0aW9uIHRoYXQgb25seSBpbnZva2VzIGBmdW5jYCBhdCBtb3N0IG9uY2UgcGVyXG4gKiBldmVyeSBgd2FpdGAgbWlsbGlzZWNvbmRzLiBUaGUgdGhyb3R0bGVkIGZ1bmN0aW9uIGNvbWVzIHdpdGggYSBgY2FuY2VsYFxuICogbWV0aG9kIHRvIGNhbmNlbCBkZWxheWVkIGBmdW5jYCBpbnZvY2F0aW9ucyBhbmQgYSBgZmx1c2hgIG1ldGhvZCB0b1xuICogaW1tZWRpYXRlbHkgaW52b2tlIHRoZW0uIFByb3ZpZGUgYG9wdGlvbnNgIHRvIGluZGljYXRlIHdoZXRoZXIgYGZ1bmNgXG4gKiBzaG91bGQgYmUgaW52b2tlZCBvbiB0aGUgbGVhZGluZyBhbmQvb3IgdHJhaWxpbmcgZWRnZSBvZiB0aGUgYHdhaXRgXG4gKiB0aW1lb3V0LiBUaGUgYGZ1bmNgIGlzIGludm9rZWQgd2l0aCB0aGUgbGFzdCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlXG4gKiB0aHJvdHRsZWQgZnVuY3Rpb24uIFN1YnNlcXVlbnQgY2FsbHMgdG8gdGhlIHRocm90dGxlZCBmdW5jdGlvbiByZXR1cm4gdGhlXG4gKiByZXN1bHQgb2YgdGhlIGxhc3QgYGZ1bmNgIGludm9jYXRpb24uXG4gKlxuICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpc1xuICogaW52b2tlZCBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dCBvbmx5IGlmIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb25cbiAqIGlzIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAqXG4gKiBJZiBgd2FpdGAgaXMgYDBgIGFuZCBgbGVhZGluZ2AgaXMgYGZhbHNlYCwgYGZ1bmNgIGludm9jYXRpb24gaXMgZGVmZXJyZWRcbiAqIHVudGlsIHRvIHRoZSBuZXh0IHRpY2ssIHNpbWlsYXIgdG8gYHNldFRpbWVvdXRgIHdpdGggYSB0aW1lb3V0IG9mIGAwYC5cbiAqXG4gKiBTZWUgW0RhdmlkIENvcmJhY2hvJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9jc3MtdHJpY2tzLmNvbS9kZWJvdW5jaW5nLXRocm90dGxpbmctZXhwbGFpbmVkLWV4YW1wbGVzLylcbiAqIGZvciBkZXRhaWxzIG92ZXIgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYF8udGhyb3R0bGVgIGFuZCBgXy5kZWJvdW5jZWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB0aHJvdHRsZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byB0aHJvdHRsZSBpbnZvY2F0aW9ucyB0by5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPXRydWVdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgbGVhZGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy50cmFpbGluZz10cnVlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB0aHJvdHRsZWQgZnVuY3Rpb24uXG4gKiBAZXhhbXBsZVxuICpcbiAqIC8vIEF2b2lkIGV4Y2Vzc2l2ZWx5IHVwZGF0aW5nIHRoZSBwb3NpdGlvbiB3aGlsZSBzY3JvbGxpbmcuXG4gKiBqUXVlcnkod2luZG93KS5vbignc2Nyb2xsJywgXy50aHJvdHRsZSh1cGRhdGVQb3NpdGlvbiwgMTAwKSk7XG4gKlxuICogLy8gSW52b2tlIGByZW5ld1Rva2VuYCB3aGVuIHRoZSBjbGljayBldmVudCBpcyBmaXJlZCwgYnV0IG5vdCBtb3JlIHRoYW4gb25jZSBldmVyeSA1IG1pbnV0ZXMuXG4gKiB2YXIgdGhyb3R0bGVkID0gXy50aHJvdHRsZShyZW5ld1Rva2VuLCAzMDAwMDAsIHsgJ3RyYWlsaW5nJzogZmFsc2UgfSk7XG4gKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgdGhyb3R0bGVkKTtcbiAqXG4gKiAvLyBDYW5jZWwgdGhlIHRyYWlsaW5nIHRocm90dGxlZCBpbnZvY2F0aW9uLlxuICogalF1ZXJ5KHdpbmRvdykub24oJ3BvcHN0YXRlJywgdGhyb3R0bGVkLmNhbmNlbCk7XG4gKi9cbmZ1bmN0aW9uIHRocm90dGxlKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcbiAgdmFyIGxlYWRpbmcgPSB0cnVlLFxuICAgICAgdHJhaWxpbmcgPSB0cnVlO1xuXG4gIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICB9XG4gIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgIGxlYWRpbmcgPSAnbGVhZGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy5sZWFkaW5nIDogbGVhZGluZztcbiAgICB0cmFpbGluZyA9ICd0cmFpbGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy50cmFpbGluZyA6IHRyYWlsaW5nO1xuICB9XG4gIHJldHVybiBkZWJvdW5jZShmdW5jLCB3YWl0LCB7XG4gICAgJ2xlYWRpbmcnOiBsZWFkaW5nLFxuICAgICdtYXhXYWl0Jzogd2FpdCxcbiAgICAndHJhaWxpbmcnOiB0cmFpbGluZ1xuICB9KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyB0aGVcbiAqIFtsYW5ndWFnZSB0eXBlXShodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtZWNtYXNjcmlwdC1sYW5ndWFnZS10eXBlcylcbiAqIG9mIGBPYmplY3RgLiAoZS5nLiBhcnJheXMsIGZ1bmN0aW9ucywgb2JqZWN0cywgcmVnZXhlcywgYG5ldyBOdW1iZXIoMClgLCBhbmQgYG5ldyBTdHJpbmcoJycpYClcbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc09iamVjdCh7fSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChbMSwgMiwgM10pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QoXy5ub29wKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KG51bGwpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gIHJldHVybiAhIXZhbHVlICYmICh0eXBlID09ICdvYmplY3QnIHx8IHR5cGUgPT0gJ2Z1bmN0aW9uJyk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UuIEEgdmFsdWUgaXMgb2JqZWN0LWxpa2UgaWYgaXQncyBub3QgYG51bGxgXG4gKiBhbmQgaGFzIGEgYHR5cGVvZmAgcmVzdWx0IG9mIFwib2JqZWN0XCIuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc09iamVjdExpa2Uoe30pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdExpa2UoXy5ub29wKTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pc09iamVjdExpa2UobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdExpa2UodmFsdWUpIHtcbiAgcmV0dXJuICEhdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09ICdvYmplY3QnO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgU3ltYm9sYCBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgc3ltYm9sLCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNTeW1ib2woU3ltYm9sLml0ZXJhdG9yKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzU3ltYm9sKCdhYmMnKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzU3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ3N5bWJvbCcgfHxcbiAgICAoaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBvYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKSA9PSBzeW1ib2xUYWcpO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBudW1iZXIuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb2Nlc3MuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBudW1iZXIuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8udG9OdW1iZXIoMy4yKTtcbiAqIC8vID0+IDMuMlxuICpcbiAqIF8udG9OdW1iZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gKiAvLyA9PiA1ZS0zMjRcbiAqXG4gKiBfLnRvTnVtYmVyKEluZmluaXR5KTtcbiAqIC8vID0+IEluZmluaXR5XG4gKlxuICogXy50b051bWJlcignMy4yJyk7XG4gKiAvLyA9PiAzLjJcbiAqL1xuZnVuY3Rpb24gdG9OdW1iZXIodmFsdWUpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJykge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICBpZiAoaXNTeW1ib2wodmFsdWUpKSB7XG4gICAgcmV0dXJuIE5BTjtcbiAgfVxuICBpZiAoaXNPYmplY3QodmFsdWUpKSB7XG4gICAgdmFyIG90aGVyID0gdHlwZW9mIHZhbHVlLnZhbHVlT2YgPT0gJ2Z1bmN0aW9uJyA/IHZhbHVlLnZhbHVlT2YoKSA6IHZhbHVlO1xuICAgIHZhbHVlID0gaXNPYmplY3Qob3RoZXIpID8gKG90aGVyICsgJycpIDogb3RoZXI7XG4gIH1cbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPSAnc3RyaW5nJykge1xuICAgIHJldHVybiB2YWx1ZSA9PT0gMCA/IHZhbHVlIDogK3ZhbHVlO1xuICB9XG4gIHZhbHVlID0gdmFsdWUucmVwbGFjZShyZVRyaW0sICcnKTtcbiAgdmFyIGlzQmluYXJ5ID0gcmVJc0JpbmFyeS50ZXN0KHZhbHVlKTtcbiAgcmV0dXJuIChpc0JpbmFyeSB8fCByZUlzT2N0YWwudGVzdCh2YWx1ZSkpXG4gICAgPyBmcmVlUGFyc2VJbnQodmFsdWUuc2xpY2UoMiksIGlzQmluYXJ5ID8gMiA6IDgpXG4gICAgOiAocmVJc0JhZEhleC50ZXN0KHZhbHVlKSA/IE5BTiA6ICt2YWx1ZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdGhyb3R0bGU7XG4iLCJ2YXIgZztcclxuXHJcbi8vIFRoaXMgd29ya3MgaW4gbm9uLXN0cmljdCBtb2RlXHJcbmcgPSAoZnVuY3Rpb24oKSB7XHJcblx0cmV0dXJuIHRoaXM7XHJcbn0pKCk7XHJcblxyXG50cnkge1xyXG5cdC8vIFRoaXMgd29ya3MgaWYgZXZhbCBpcyBhbGxvd2VkIChzZWUgQ1NQKVxyXG5cdGcgPSBnIHx8IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKSB8fCAoMSwgZXZhbCkoXCJ0aGlzXCIpO1xyXG59IGNhdGNoIChlKSB7XHJcblx0Ly8gVGhpcyB3b3JrcyBpZiB0aGUgd2luZG93IHJlZmVyZW5jZSBpcyBhdmFpbGFibGVcclxuXHRpZiAodHlwZW9mIHdpbmRvdyA9PT0gXCJvYmplY3RcIikgZyA9IHdpbmRvdztcclxufVxyXG5cclxuLy8gZyBjYW4gc3RpbGwgYmUgdW5kZWZpbmVkLCBidXQgbm90aGluZyB0byBkbyBhYm91dCBpdC4uLlxyXG4vLyBXZSByZXR1cm4gdW5kZWZpbmVkLCBpbnN0ZWFkIG9mIG5vdGhpbmcgaGVyZSwgc28gaXQnc1xyXG4vLyBlYXNpZXIgdG8gaGFuZGxlIHRoaXMgY2FzZS4gaWYoIWdsb2JhbCkgeyAuLi59XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGc7XHJcbiIsIi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuaW1wb3J0IHsgZ2V0RWxlbWVudHNGb3JTb3VyY2VMaW5lIH0gZnJvbSAnLi9zY3JvbGwtc3luYyc7XG5cbmV4cG9ydCBjbGFzcyBBY3RpdmVMaW5lTWFya2VyIHtcblx0cHJpdmF0ZSBfY3VycmVudDogYW55O1xuXG5cdG9uRGlkQ2hhbmdlVGV4dEVkaXRvclNlbGVjdGlvbihsaW5lOiBudW1iZXIpIHtcblx0XHRjb25zdCB7IHByZXZpb3VzIH0gPSBnZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUobGluZSk7XG5cdFx0dGhpcy5fdXBkYXRlKHByZXZpb3VzICYmIHByZXZpb3VzLmVsZW1lbnQpO1xuXHR9XG5cblx0X3VwZGF0ZShiZWZvcmU6IEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkKSB7XG5cdFx0dGhpcy5fdW5tYXJrQWN0aXZlRWxlbWVudCh0aGlzLl9jdXJyZW50KTtcblx0XHR0aGlzLl9tYXJrQWN0aXZlRWxlbWVudChiZWZvcmUpO1xuXHRcdHRoaXMuX2N1cnJlbnQgPSBiZWZvcmU7XG5cdH1cblxuXHRfdW5tYXJrQWN0aXZlRWxlbWVudChlbGVtZW50OiBIVE1MRWxlbWVudCB8IHVuZGVmaW5lZCkge1xuXHRcdGlmICghZWxlbWVudCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRlbGVtZW50LmNsYXNzTmFtZSA9IGVsZW1lbnQuY2xhc3NOYW1lLnJlcGxhY2UoL1xcYmNvZGUtYWN0aXZlLWxpbmVcXGIvZywgJycpO1xuXHR9XG5cblx0X21hcmtBY3RpdmVFbGVtZW50KGVsZW1lbnQ6IEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkKSB7XG5cdFx0aWYgKCFlbGVtZW50KSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGVsZW1lbnQuY2xhc3NOYW1lICs9ICcgY29kZS1hY3RpdmUtbGluZSc7XG5cdH1cbn0iLCIvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG9uY2VEb2N1bWVudExvYWRlZChmOiAoKSA9PiB2b2lkKSB7XG5cdGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnbG9hZGluZycgfHwgZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ3VuaW5pdGlhbGl6ZWQnKSB7XG5cdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGYpO1xuXHR9IGVsc2Uge1xuXHRcdGYoKTtcblx0fVxufSIsIi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5pbXBvcnQgeyBBY3RpdmVMaW5lTWFya2VyIH0gZnJvbSAnLi9hY3RpdmVMaW5lTWFya2VyJztcbmltcG9ydCB7IG9uY2VEb2N1bWVudExvYWRlZCB9IGZyb20gJy4vZXZlbnRzJztcbmltcG9ydCB7IGNyZWF0ZVBvc3RlckZvclZzQ29kZSB9IGZyb20gJy4vbWVzc2FnaW5nJztcbmltcG9ydCB7IGdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0LCBzY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUgfSBmcm9tICcuL3Njcm9sbC1zeW5jJztcbmltcG9ydCB7IGdldFNldHRpbmdzLCBnZXREYXRhIH0gZnJvbSAnLi9zZXR0aW5ncyc7XG5pbXBvcnQgdGhyb3R0bGUgPSByZXF1aXJlKCdsb2Rhc2gudGhyb3R0bGUnKTtcblxuZGVjbGFyZSB2YXIgYWNxdWlyZVZzQ29kZUFwaTogYW55O1xuXG52YXIgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuY29uc3QgbWFya2VyID0gbmV3IEFjdGl2ZUxpbmVNYXJrZXIoKTtcbmNvbnN0IHNldHRpbmdzID0gZ2V0U2V0dGluZ3MoKTtcblxuY29uc3QgdnNjb2RlID0gYWNxdWlyZVZzQ29kZUFwaSgpO1xuXG4vLyBTZXQgVlMgQ29kZSBzdGF0ZVxuY29uc3Qgc3RhdGUgPSBnZXREYXRhKCdkYXRhLXN0YXRlJyk7XG52c2NvZGUuc2V0U3RhdGUoc3RhdGUpO1xuXG5jb25zdCBtZXNzYWdpbmcgPSBjcmVhdGVQb3N0ZXJGb3JWc0NvZGUodnNjb2RlKTtcblxud2luZG93LmNzcEFsZXJ0ZXIuc2V0UG9zdGVyKG1lc3NhZ2luZyk7XG53aW5kb3cuc3R5bGVMb2FkaW5nTW9uaXRvci5zZXRQb3N0ZXIobWVzc2FnaW5nKTtcblxud2luZG93Lm9ubG9hZCA9ICgpID0+IHtcblx0dXBkYXRlSW1hZ2VTaXplcygpO1xufTtcblxub25jZURvY3VtZW50TG9hZGVkKCgpID0+IHtcblx0aWYgKHNldHRpbmdzLnNjcm9sbFByZXZpZXdXaXRoRWRpdG9yKSB7XG5cdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRjb25zdCBpbml0aWFsTGluZSA9ICtzZXR0aW5ncy5saW5lO1xuXHRcdFx0aWYgKCFpc05hTihpbml0aWFsTGluZSkpIHtcblx0XHRcdFx0c2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuXHRcdFx0XHRzY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUoaW5pdGlhbExpbmUpO1xuXHRcdFx0fVxuXHRcdH0sIDApO1xuXHR9XG59KTtcblxuY29uc3Qgb25VcGRhdGVWaWV3ID0gKCgpID0+IHtcblx0Y29uc3QgZG9TY3JvbGwgPSB0aHJvdHRsZSgobGluZTogbnVtYmVyKSA9PiB7XG5cdFx0c2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuXHRcdHNjcm9sbFRvUmV2ZWFsU291cmNlTGluZShsaW5lKTtcblx0fSwgNTApO1xuXG5cdHJldHVybiAobGluZTogbnVtYmVyLCBzZXR0aW5nczogYW55KSA9PiB7XG5cdFx0aWYgKCFpc05hTihsaW5lKSkge1xuXHRcdFx0c2V0dGluZ3MubGluZSA9IGxpbmU7XG5cdFx0XHRkb1Njcm9sbChsaW5lKTtcblx0XHR9XG5cdH07XG59KSgpO1xuXG5sZXQgdXBkYXRlSW1hZ2VTaXplcyA9IHRocm90dGxlKCgpID0+IHtcblx0Y29uc3QgaW1hZ2VJbmZvOiB7IGlkOiBzdHJpbmcsIGhlaWdodDogbnVtYmVyLCB3aWR0aDogbnVtYmVyIH1bXSA9IFtdO1xuXHRsZXQgaW1hZ2VzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2ltZycpO1xuXHRpZiAoaW1hZ2VzKSB7XG5cdFx0bGV0IGk7XG5cdFx0Zm9yIChpID0gMDsgaSA8IGltYWdlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3QgaW1nID0gaW1hZ2VzW2ldO1xuXG5cdFx0XHRpZiAoaW1nLmNsYXNzTGlzdC5jb250YWlucygnbG9hZGluZycpKSB7XG5cdFx0XHRcdGltZy5jbGFzc0xpc3QucmVtb3ZlKCdsb2FkaW5nJyk7XG5cdFx0XHR9XG5cblx0XHRcdGltYWdlSW5mby5wdXNoKHtcblx0XHRcdFx0aWQ6IGltZy5pZCxcblx0XHRcdFx0aGVpZ2h0OiBpbWcuaGVpZ2h0LFxuXHRcdFx0XHR3aWR0aDogaW1nLndpZHRoXG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ2NhY2hlSW1hZ2VTaXplcycsIGltYWdlSW5mbyk7XG5cdH1cbn0sIDUwKTtcblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsICgpID0+IHtcblx0c2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuXHR1cGRhdGVJbWFnZVNpemVzKCk7XG59LCB0cnVlKTtcblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBldmVudCA9PiB7XG5cdGlmIChldmVudC5kYXRhLnNvdXJjZSAhPT0gc2V0dGluZ3Muc291cmNlKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0c3dpdGNoIChldmVudC5kYXRhLnR5cGUpIHtcblx0XHRjYXNlICdvbkRpZENoYW5nZVRleHRFZGl0b3JTZWxlY3Rpb24nOlxuXHRcdFx0bWFya2VyLm9uRGlkQ2hhbmdlVGV4dEVkaXRvclNlbGVjdGlvbihldmVudC5kYXRhLmxpbmUpO1xuXHRcdFx0YnJlYWs7XG5cblx0XHRjYXNlICd1cGRhdGVWaWV3Jzpcblx0XHRcdG9uVXBkYXRlVmlldyhldmVudC5kYXRhLmxpbmUsIHNldHRpbmdzKTtcblx0XHRcdGJyZWFrO1xuXHR9XG59LCBmYWxzZSk7XG5cbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgZXZlbnQgPT4ge1xuXHRpZiAoIXNldHRpbmdzLmRvdWJsZUNsaWNrVG9Td2l0Y2hUb0VkaXRvcikge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdC8vIElnbm9yZSBjbGlja3Mgb24gbGlua3Ncblx0Zm9yIChsZXQgbm9kZSA9IGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudDsgbm9kZTsgbm9kZSA9IG5vZGUucGFyZW50Tm9kZSBhcyBIVE1MRWxlbWVudCkge1xuXHRcdGlmIChub2RlLnRhZ05hbWUgPT09ICdBJykge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0fVxuXG5cdGNvbnN0IG9mZnNldCA9IGV2ZW50LnBhZ2VZO1xuXHRjb25zdCBsaW5lID0gZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQob2Zmc2V0KTtcblx0aWYgKHR5cGVvZiBsaW5lID09PSAnbnVtYmVyJyAmJiAhaXNOYU4obGluZSkpIHtcblx0XHRtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ2RpZENsaWNrJywgeyBsaW5lOiBNYXRoLmZsb29yKGxpbmUpIH0pO1xuXHR9XG59KTtcblxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBldmVudCA9PiB7XG5cdGlmICghZXZlbnQpIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRsZXQgbm9kZTogYW55ID0gZXZlbnQudGFyZ2V0O1xuXHR3aGlsZSAobm9kZSkge1xuXHRcdGlmIChub2RlLnRhZ05hbWUgJiYgbm9kZS50YWdOYW1lID09PSAnQScgJiYgbm9kZS5ocmVmKSB7XG5cdFx0XHRpZiAobm9kZS5nZXRBdHRyaWJ1dGUoJ2hyZWYnKS5zdGFydHNXaXRoKCcjJykpIHtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRpZiAobm9kZS5ocmVmLnN0YXJ0c1dpdGgoJ2ZpbGU6Ly8nKSB8fCBub2RlLmhyZWYuc3RhcnRzV2l0aCgndnNjb2RlLXJlc291cmNlOicpKSB7XG5cdFx0XHRcdGNvbnN0IFtwYXRoLCBmcmFnbWVudF0gPSBub2RlLmhyZWYucmVwbGFjZSgvXihmaWxlOlxcL1xcL3x2c2NvZGUtcmVzb3VyY2U6KS9pLCAnJykuc3BsaXQoJyMnKTtcblx0XHRcdFx0bWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdjbGlja0xpbmsnLCB7IHBhdGgsIGZyYWdtZW50IH0pO1xuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdFx0bm9kZSA9IG5vZGUucGFyZW50Tm9kZTtcblx0fVxufSwgdHJ1ZSk7XG5cbmlmIChzZXR0aW5ncy5zY3JvbGxFZGl0b3JXaXRoUHJldmlldykge1xuXHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhyb3R0bGUoKCkgPT4ge1xuXHRcdGlmIChzY3JvbGxEaXNhYmxlZCkge1xuXHRcdFx0c2Nyb2xsRGlzYWJsZWQgPSBmYWxzZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y29uc3QgbGluZSA9IGdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0KHdpbmRvdy5zY3JvbGxZKTtcblx0XHRcdGlmICh0eXBlb2YgbGluZSA9PT0gJ251bWJlcicgJiYgIWlzTmFOKGxpbmUpKSB7XG5cdFx0XHRcdG1lc3NhZ2luZy5wb3N0TWVzc2FnZSgncmV2ZWFsTGluZScsIHsgbGluZSB9KTtcblx0XHRcdH1cblx0XHR9XG5cdH0sIDUwKSk7XG59IiwiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbmltcG9ydCB7IGdldFNldHRpbmdzIH0gZnJvbSAnLi9zZXR0aW5ncyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVzc2FnZVBvc3RlciB7XG5cdC8qKlxuXHQgKiBQb3N0IGEgbWVzc2FnZSB0byB0aGUgbWFya2Rvd24gZXh0ZW5zaW9uXG5cdCAqL1xuXHRwb3N0TWVzc2FnZSh0eXBlOiBzdHJpbmcsIGJvZHk6IG9iamVjdCk6IHZvaWQ7XG59XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVQb3N0ZXJGb3JWc0NvZGUgPSAodnNjb2RlOiBhbnkpID0+IHtcblx0cmV0dXJuIG5ldyBjbGFzcyBpbXBsZW1lbnRzIE1lc3NhZ2VQb3N0ZXIge1xuXHRcdHBvc3RNZXNzYWdlKHR5cGU6IHN0cmluZywgYm9keTogb2JqZWN0KTogdm9pZCB7XG5cdFx0XHR2c2NvZGUucG9zdE1lc3NhZ2Uoe1xuXHRcdFx0XHR0eXBlLFxuXHRcdFx0XHRzb3VyY2U6IGdldFNldHRpbmdzKCkuc291cmNlLFxuXHRcdFx0XHRib2R5XG5cdFx0XHR9KTtcblx0XHR9XG5cdH07XG59O1xuXG4iLCIvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuaW1wb3J0IHsgZ2V0U2V0dGluZ3MgfSBmcm9tICcuL3NldHRpbmdzJztcblxuXG5mdW5jdGlvbiBjbGFtcChtaW46IG51bWJlciwgbWF4OiBudW1iZXIsIHZhbHVlOiBudW1iZXIpIHtcblx0cmV0dXJuIE1hdGgubWluKG1heCwgTWF0aC5tYXgobWluLCB2YWx1ZSkpO1xufVxuXG5mdW5jdGlvbiBjbGFtcExpbmUobGluZTogbnVtYmVyKSB7XG5cdHJldHVybiBjbGFtcCgwLCBnZXRTZXR0aW5ncygpLmxpbmVDb3VudCAtIDEsIGxpbmUpO1xufVxuXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29kZUxpbmVFbGVtZW50IHtcblx0ZWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cdGxpbmU6IG51bWJlcjtcbn1cblxuY29uc3QgZ2V0Q29kZUxpbmVFbGVtZW50cyA9ICgoKSA9PiB7XG5cdGxldCBlbGVtZW50czogQ29kZUxpbmVFbGVtZW50W107XG5cdHJldHVybiAoKSA9PiB7XG5cdFx0aWYgKCFlbGVtZW50cykge1xuXHRcdFx0ZWxlbWVudHMgPSAoW3sgZWxlbWVudDogZG9jdW1lbnQuYm9keSwgbGluZTogMCB9XSkuY29uY2F0KEFycmF5LnByb3RvdHlwZS5tYXAuY2FsbChcblx0XHRcdFx0ZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnY29kZS1saW5lJyksXG5cdFx0XHRcdChlbGVtZW50OiBhbnkpID0+IHtcblx0XHRcdFx0XHRjb25zdCBsaW5lID0gK2VsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLWxpbmUnKTtcblx0XHRcdFx0XHRyZXR1cm4geyBlbGVtZW50LCBsaW5lIH07XG5cdFx0XHRcdH0pXG5cdFx0XHRcdC5maWx0ZXIoKHg6IGFueSkgPT4gIWlzTmFOKHgubGluZSkpKTtcblx0XHR9XG5cdFx0cmV0dXJuIGVsZW1lbnRzO1xuXHR9O1xufSkoKTtcblxuLyoqXG4gKiBGaW5kIHRoZSBodG1sIGVsZW1lbnRzIHRoYXQgbWFwIHRvIGEgc3BlY2lmaWMgdGFyZ2V0IGxpbmUgaW4gdGhlIGVkaXRvci5cbiAqXG4gKiBJZiBhbiBleGFjdCBtYXRjaCwgcmV0dXJucyBhIHNpbmdsZSBlbGVtZW50LiBJZiB0aGUgbGluZSBpcyBiZXR3ZWVuIGVsZW1lbnRzLFxuICogcmV0dXJucyB0aGUgZWxlbWVudCBwcmlvciB0byBhbmQgdGhlIGVsZW1lbnQgYWZ0ZXIgdGhlIGdpdmVuIGxpbmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUodGFyZ2V0TGluZTogbnVtYmVyKTogeyBwcmV2aW91czogQ29kZUxpbmVFbGVtZW50OyBuZXh0PzogQ29kZUxpbmVFbGVtZW50OyB9IHtcblx0Y29uc3QgbGluZU51bWJlciA9IE1hdGguZmxvb3IodGFyZ2V0TGluZSk7XG5cdGNvbnN0IGxpbmVzID0gZ2V0Q29kZUxpbmVFbGVtZW50cygpO1xuXHRsZXQgcHJldmlvdXMgPSBsaW5lc1swXSB8fCBudWxsO1xuXHRmb3IgKGNvbnN0IGVudHJ5IG9mIGxpbmVzKSB7XG5cdFx0aWYgKGVudHJ5LmxpbmUgPT09IGxpbmVOdW1iZXIpIHtcblx0XHRcdHJldHVybiB7IHByZXZpb3VzOiBlbnRyeSwgbmV4dDogdW5kZWZpbmVkIH07XG5cdFx0fSBlbHNlIGlmIChlbnRyeS5saW5lID4gbGluZU51bWJlcikge1xuXHRcdFx0cmV0dXJuIHsgcHJldmlvdXMsIG5leHQ6IGVudHJ5IH07XG5cdFx0fVxuXHRcdHByZXZpb3VzID0gZW50cnk7XG5cdH1cblx0cmV0dXJuIHsgcHJldmlvdXMgfTtcbn1cblxuLyoqXG4gKiBGaW5kIHRoZSBodG1sIGVsZW1lbnRzIHRoYXQgYXJlIGF0IGEgc3BlY2lmaWMgcGl4ZWwgb2Zmc2V0IG9uIHRoZSBwYWdlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0KG9mZnNldDogbnVtYmVyKTogeyBwcmV2aW91czogQ29kZUxpbmVFbGVtZW50OyBuZXh0PzogQ29kZUxpbmVFbGVtZW50OyB9IHtcblx0Y29uc3QgbGluZXMgPSBnZXRDb2RlTGluZUVsZW1lbnRzKCk7XG5cdGNvbnN0IHBvc2l0aW9uID0gb2Zmc2V0IC0gd2luZG93LnNjcm9sbFk7XG5cdGxldCBsbyA9IC0xO1xuXHRsZXQgaGkgPSBsaW5lcy5sZW5ndGggLSAxO1xuXHR3aGlsZSAobG8gKyAxIDwgaGkpIHtcblx0XHRjb25zdCBtaWQgPSBNYXRoLmZsb29yKChsbyArIGhpKSAvIDIpO1xuXHRcdGNvbnN0IGJvdW5kcyA9IGxpbmVzW21pZF0uZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0XHRpZiAoYm91bmRzLnRvcCArIGJvdW5kcy5oZWlnaHQgPj0gcG9zaXRpb24pIHtcblx0XHRcdGhpID0gbWlkO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGxvID0gbWlkO1xuXHRcdH1cblx0fVxuXHRjb25zdCBoaUVsZW1lbnQgPSBsaW5lc1toaV07XG5cdGNvbnN0IGhpQm91bmRzID0gaGlFbGVtZW50LmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cdGlmIChoaSA+PSAxICYmIGhpQm91bmRzLnRvcCA+IHBvc2l0aW9uKSB7XG5cdFx0Y29uc3QgbG9FbGVtZW50ID0gbGluZXNbbG9dO1xuXHRcdHJldHVybiB7IHByZXZpb3VzOiBsb0VsZW1lbnQsIG5leHQ6IGhpRWxlbWVudCB9O1xuXHR9XG5cdHJldHVybiB7IHByZXZpb3VzOiBoaUVsZW1lbnQgfTtcbn1cblxuLyoqXG4gKiBBdHRlbXB0IHRvIHJldmVhbCB0aGUgZWxlbWVudCBmb3IgYSBzb3VyY2UgbGluZSBpbiB0aGUgZWRpdG9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lKGxpbmU6IG51bWJlcikge1xuXHRpZiAoIWdldFNldHRpbmdzKCkuc2Nyb2xsUHJldmlld1dpdGhFZGl0b3IpIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRpZiAobGluZSA8PSAwKSB7XG5cdFx0d2luZG93LnNjcm9sbCh3aW5kb3cuc2Nyb2xsWCwgMCk7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0Y29uc3QgeyBwcmV2aW91cywgbmV4dCB9ID0gZ2V0RWxlbWVudHNGb3JTb3VyY2VMaW5lKGxpbmUpO1xuXHRpZiAoIXByZXZpb3VzKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGxldCBzY3JvbGxUbyA9IDA7XG5cdGNvbnN0IHJlY3QgPSBwcmV2aW91cy5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXHRjb25zdCBwcmV2aW91c1RvcCA9IHJlY3QudG9wO1xuXHRpZiAobmV4dCAmJiBuZXh0LmxpbmUgIT09IHByZXZpb3VzLmxpbmUpIHtcblx0XHQvLyBCZXR3ZWVuIHR3byBlbGVtZW50cy4gR28gdG8gcGVyY2VudGFnZSBvZmZzZXQgYmV0d2VlbiB0aGVtLlxuXHRcdGNvbnN0IGJldHdlZW5Qcm9ncmVzcyA9IChsaW5lIC0gcHJldmlvdXMubGluZSkgLyAobmV4dC5saW5lIC0gcHJldmlvdXMubGluZSk7XG5cdFx0Y29uc3QgZWxlbWVudE9mZnNldCA9IG5leHQuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLSBwcmV2aW91c1RvcDtcblx0XHRzY3JvbGxUbyA9IHByZXZpb3VzVG9wICsgYmV0d2VlblByb2dyZXNzICogZWxlbWVudE9mZnNldDtcblx0fSBlbHNlIHtcblx0XHRjb25zdCBwcm9ncmVzc0luRWxlbWVudCA9IGxpbmUgLSBNYXRoLmZsb29yKGxpbmUpO1xuXHRcdHNjcm9sbFRvID0gcHJldmlvdXNUb3AgKyAocmVjdC5oZWlnaHQgKiBwcm9ncmVzc0luRWxlbWVudCk7XG5cdH1cblx0d2luZG93LnNjcm9sbCh3aW5kb3cuc2Nyb2xsWCwgTWF0aC5tYXgoMSwgd2luZG93LnNjcm9sbFkgKyBzY3JvbGxUbykpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQob2Zmc2V0OiBudW1iZXIpIHtcblx0Y29uc3QgeyBwcmV2aW91cywgbmV4dCB9ID0gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0KG9mZnNldCk7XG5cdGlmIChwcmV2aW91cykge1xuXHRcdGNvbnN0IHByZXZpb3VzQm91bmRzID0gcHJldmlvdXMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0XHRjb25zdCBvZmZzZXRGcm9tUHJldmlvdXMgPSAob2Zmc2V0IC0gd2luZG93LnNjcm9sbFkgLSBwcmV2aW91c0JvdW5kcy50b3ApO1xuXHRcdGlmIChuZXh0KSB7XG5cdFx0XHRjb25zdCBwcm9ncmVzc0JldHdlZW5FbGVtZW50cyA9IG9mZnNldEZyb21QcmV2aW91cyAvIChuZXh0LmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wIC0gcHJldmlvdXNCb3VuZHMudG9wKTtcblx0XHRcdGNvbnN0IGxpbmUgPSBwcmV2aW91cy5saW5lICsgcHJvZ3Jlc3NCZXR3ZWVuRWxlbWVudHMgKiAobmV4dC5saW5lIC0gcHJldmlvdXMubGluZSk7XG5cdFx0XHRyZXR1cm4gY2xhbXBMaW5lKGxpbmUpO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGNvbnN0IHByb2dyZXNzV2l0aGluRWxlbWVudCA9IG9mZnNldEZyb21QcmV2aW91cyAvIChwcmV2aW91c0JvdW5kcy5oZWlnaHQpO1xuXHRcdFx0Y29uc3QgbGluZSA9IHByZXZpb3VzLmxpbmUgKyBwcm9ncmVzc1dpdGhpbkVsZW1lbnQ7XG5cdFx0XHRyZXR1cm4gY2xhbXBMaW5lKGxpbmUpO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gbnVsbDtcbn1cbiIsIi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5leHBvcnQgaW50ZXJmYWNlIFByZXZpZXdTZXR0aW5ncyB7XG5cdHNvdXJjZTogc3RyaW5nO1xuXHRsaW5lOiBudW1iZXI7XG5cdGxpbmVDb3VudDogbnVtYmVyO1xuXHRzY3JvbGxQcmV2aWV3V2l0aEVkaXRvcj86IGJvb2xlYW47XG5cdHNjcm9sbEVkaXRvcldpdGhQcmV2aWV3OiBib29sZWFuO1xuXHRkaXNhYmxlU2VjdXJpdHlXYXJuaW5nczogYm9vbGVhbjtcblx0ZG91YmxlQ2xpY2tUb1N3aXRjaFRvRWRpdG9yOiBib29sZWFuO1xufVxuXG5sZXQgY2FjaGVkU2V0dGluZ3M6IFByZXZpZXdTZXR0aW5ncyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldERhdGEoa2V5OiBzdHJpbmcpOiBQcmV2aWV3U2V0dGluZ3Mge1xuXHRjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3ZzY29kZS1tYXJrZG93bi1wcmV2aWV3LWRhdGEnKTtcblx0aWYgKGVsZW1lbnQpIHtcblx0XHRjb25zdCBkYXRhID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoa2V5KTtcblx0XHRpZiAoZGF0YSkge1xuXHRcdFx0cmV0dXJuIEpTT04ucGFyc2UoZGF0YSk7XG5cdFx0fVxuXHR9XG5cblx0dGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgbG9hZCBkYXRhIGZvciAke2tleX1gKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNldHRpbmdzKCk6IFByZXZpZXdTZXR0aW5ncyB7XG5cdGlmIChjYWNoZWRTZXR0aW5ncykge1xuXHRcdHJldHVybiBjYWNoZWRTZXR0aW5ncztcblx0fVxuXG5cdGNhY2hlZFNldHRpbmdzID0gZ2V0RGF0YSgnZGF0YS1zZXR0aW5ncycpO1xuXHRpZiAoY2FjaGVkU2V0dGluZ3MpIHtcblx0XHRyZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG5cdH1cblxuXHR0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCBsb2FkIHNldHRpbmdzJyk7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2xvZGFzaC50aHJvdHRsZS9pbmRleC5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2FjdGl2ZUxpbmVNYXJrZXIudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvZXZlbnRzLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2luZGV4LnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL21lc3NhZ2luZy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zY3JvbGwtc3luYy50cyIsIndlYnBhY2s6Ly8vLi9wcmV2aWV3LXNyYy9zZXR0aW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSx5REFBaUQsY0FBYztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBMkIsMEJBQTBCLEVBQUU7QUFDdkQseUNBQWlDLGVBQWU7QUFDaEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOERBQXNELCtEQUErRDs7QUFFckg7QUFDQTs7O0FBR0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLDhDQUE4QyxrQkFBa0I7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTyxZQUFZO0FBQzlCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQsb0JBQW9CO0FBQ3ZFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsRUFBRTtBQUNiLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxFQUFFO0FBQ2IsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7Ozs7O0FDdGJBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNENBQTRDOztBQUU1Qzs7Ozs7Ozs7Ozs7Ozs7O0FDbkJBOzs7Z0dBR2dHO0FBQ2hHLCtGQUF5RDtBQUV6RCxNQUFhLGdCQUFnQjtJQUc1Qiw4QkFBOEIsQ0FBQyxJQUFZO1FBQzFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxzQ0FBd0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsSUFBSSxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVELE9BQU8sQ0FBQyxNQUErQjtRQUN0QyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNoQyxJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQztJQUN4QixDQUFDO0lBRUQsb0JBQW9CLENBQUMsT0FBZ0M7UUFDcEQsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNiLE9BQU87U0FDUDtRQUNELE9BQU8sQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsdUJBQXVCLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDNUUsQ0FBQztJQUVELGtCQUFrQixDQUFDLE9BQWdDO1FBQ2xELElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDYixPQUFPO1NBQ1A7UUFDRCxPQUFPLENBQUMsU0FBUyxJQUFJLG1CQUFtQixDQUFDO0lBQzFDLENBQUM7Q0FDRDtBQTNCRCw0Q0EyQkM7Ozs7Ozs7Ozs7Ozs7O0FDakNEOzs7Z0dBR2dHOztBQUVoRyxTQUFnQixrQkFBa0IsQ0FBQyxDQUFhO0lBQy9DLElBQUksUUFBUSxDQUFDLFVBQVUsS0FBSyxTQUFTLElBQUksUUFBUSxDQUFDLFVBQW9CLEtBQUssZUFBZSxFQUFFO1FBQzNGLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLENBQUMsQ0FBQztLQUNqRDtTQUFNO1FBQ04sQ0FBQyxFQUFFLENBQUM7S0FDSjtBQUNGLENBQUM7QUFORCxnREFNQzs7Ozs7Ozs7Ozs7Ozs7QUNYRDs7O2dHQUdnRzs7QUFFaEcsOEdBQXNEO0FBQ3RELGdGQUE4QztBQUM5Qyx5RkFBb0Q7QUFDcEQsK0ZBQTJGO0FBQzNGLHNGQUFrRDtBQUNsRCx1R0FBNkM7QUFJN0MsSUFBSSxjQUFjLEdBQUcsSUFBSSxDQUFDO0FBQzFCLE1BQU0sTUFBTSxHQUFHLElBQUksbUNBQWdCLEVBQUUsQ0FBQztBQUN0QyxNQUFNLFFBQVEsR0FBRyxzQkFBVyxFQUFFLENBQUM7QUFFL0IsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLEVBQUUsQ0FBQztBQUVsQyxvQkFBb0I7QUFDcEIsSUFBSSxLQUFLLEdBQUcsa0JBQU8sQ0FBbUIsWUFBWSxDQUFDLENBQUM7QUFDcEQsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUV2QixNQUFNLFNBQVMsR0FBRyxpQ0FBcUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUVoRCxNQUFNLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUN2QyxNQUFNLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBRWhELE1BQU0sQ0FBQyxNQUFNLEdBQUcsR0FBRyxFQUFFO0lBQ3BCLGdCQUFnQixFQUFFLENBQUM7QUFDcEIsQ0FBQyxDQUFDO0FBRUYsMkJBQWtCLENBQUMsR0FBRyxFQUFFO0lBQ3ZCLElBQUksUUFBUSxDQUFDLHVCQUF1QixFQUFFO1FBQ3JDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZixNQUFNLFdBQVcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7WUFDbkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRTtnQkFDeEIsY0FBYyxHQUFHLElBQUksQ0FBQztnQkFDdEIsc0NBQXdCLENBQUMsV0FBVyxDQUFDLENBQUM7YUFDdEM7UUFDRixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7S0FDTjtBQUNGLENBQUMsQ0FBQyxDQUFDO0FBRUgsTUFBTSxZQUFZLEdBQUcsQ0FBQyxHQUFHLEVBQUU7SUFDMUIsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLENBQUMsSUFBWSxFQUFFLEVBQUU7UUFDMUMsY0FBYyxHQUFHLElBQUksQ0FBQztRQUN0QixzQ0FBd0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFUCxPQUFPLENBQUMsSUFBWSxFQUFFLFFBQWEsRUFBRSxFQUFFO1FBQ3RDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDakIsUUFBUSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7WUFDckIsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ2Y7SUFDRixDQUFDLENBQUM7QUFDSCxDQUFDLENBQUMsRUFBRSxDQUFDO0FBRUwsSUFBSSxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO0lBQ3BDLE1BQU0sU0FBUyxHQUFvRCxFQUFFLENBQUM7SUFDdEUsSUFBSSxNQUFNLEdBQUcsUUFBUSxDQUFDLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2xELElBQUksTUFBTSxFQUFFO1FBQ1gsSUFBSSxDQUFDLENBQUM7UUFDTixLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDbkMsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRXRCLElBQUksR0FBRyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEVBQUU7Z0JBQ3RDLEdBQUcsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQ2hDO1lBRUQsU0FBUyxDQUFDLElBQUksQ0FBQztnQkFDZCxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQUU7Z0JBQ1YsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNO2dCQUNsQixLQUFLLEVBQUUsR0FBRyxDQUFDLEtBQUs7YUFDaEIsQ0FBQyxDQUFDO1NBQ0g7UUFFRCxTQUFTLENBQUMsV0FBVyxDQUFDLGlCQUFpQixFQUFFLFNBQVMsQ0FBQyxDQUFDO0tBQ3BEO0FBQ0YsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBRVAsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxHQUFHLEVBQUU7SUFDdEMsY0FBYyxHQUFHLElBQUksQ0FBQztJQUN0QixnQkFBZ0IsRUFBRSxDQUFDO0FBQ3BCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUVULE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLEVBQUU7SUFDMUMsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxRQUFRLENBQUMsTUFBTSxFQUFFO1FBQzFDLE9BQU87S0FDUDtJQUVELFFBQVEsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7UUFDeEIsS0FBSyxnQ0FBZ0M7WUFDcEMsTUFBTSxDQUFDLDhCQUE4QixDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdkQsTUFBTTtRQUVQLEtBQUssWUFBWTtZQUNoQixZQUFZLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDeEMsTUFBTTtLQUNQO0FBQ0YsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBRVYsUUFBUSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsRUFBRTtJQUM3QyxJQUFJLENBQUMsUUFBUSxDQUFDLDJCQUEyQixFQUFFO1FBQzFDLE9BQU87S0FDUDtJQUVELHlCQUF5QjtJQUN6QixLQUFLLElBQUksSUFBSSxHQUFHLEtBQUssQ0FBQyxNQUFxQixFQUFFLElBQUksRUFBRSxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQXlCLEVBQUU7UUFDekYsSUFBSSxJQUFJLENBQUMsT0FBTyxLQUFLLEdBQUcsRUFBRTtZQUN6QixPQUFPO1NBQ1A7S0FDRDtJQUVELE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7SUFDM0IsTUFBTSxJQUFJLEdBQUcsOENBQWdDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEQsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDN0MsU0FBUyxDQUFDLFdBQVcsQ0FBQyxVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7S0FDOUQ7QUFDRixDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLEVBQUU7SUFDMUMsSUFBSSxDQUFDLEtBQUssRUFBRTtRQUNYLE9BQU87S0FDUDtJQUVELElBQUksSUFBSSxHQUFRLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFDN0IsT0FBTyxJQUFJLEVBQUU7UUFDWixJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLE9BQU8sS0FBSyxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksRUFBRTtZQUN0RCxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFO2dCQUM5QyxNQUFNO2FBQ047WUFDRCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLGtCQUFrQixDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUFDLEVBQUU7Z0JBQ3RJLE1BQU0sQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsZ0NBQWdDLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksTUFBTSxDQUFDLElBQUksWUFBWSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDbEssU0FBUyxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztnQkFDdkQsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUN2QixLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQ3hCLE1BQU07YUFDTjtZQUNELE1BQU07U0FDTjtRQUNELElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO0tBQ3ZCO0FBQ0YsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBRVQsSUFBSSxRQUFRLENBQUMsdUJBQXVCLEVBQUU7SUFDckMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsR0FBRyxFQUFFO1FBQy9DLElBQUksY0FBYyxFQUFFO1lBQ25CLGNBQWMsR0FBRyxLQUFLLENBQUM7U0FDdkI7YUFBTTtZQUNOLE1BQU0sSUFBSSxHQUFHLDhDQUFnQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM5RCxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRTtnQkFDN0MsU0FBUyxDQUFDLFdBQVcsQ0FBQyxZQUFZLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUM5QyxLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztnQkFDbEIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUN2QjtTQUNEO0lBQ0YsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7Q0FDUjtBQUVELFNBQVMsWUFBWSxDQUFDLElBQVk7SUFDakMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLDBCQUEwQixFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ3pELENBQUM7Ozs7Ozs7Ozs7Ozs7O0FDbktEOzs7Z0dBR2dHOztBQUVoRyxzRkFBeUM7QUFTNUIsNkJBQXFCLEdBQUcsQ0FBQyxNQUFXLEVBQUUsRUFBRTtJQUNwRCxPQUFPLElBQUk7UUFDVixXQUFXLENBQUMsSUFBWSxFQUFFLElBQVk7WUFDckMsTUFBTSxDQUFDLFdBQVcsQ0FBQztnQkFDbEIsSUFBSTtnQkFDSixNQUFNLEVBQUUsc0JBQVcsRUFBRSxDQUFDLE1BQU07Z0JBQzVCLElBQUk7YUFDSixDQUFDLENBQUM7UUFDSixDQUFDO0tBQ0QsQ0FBQztBQUNILENBQUMsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7QUN4QkY7OztnR0FHZ0c7O0FBRWhHLHNGQUF5QztBQUd6QyxTQUFTLEtBQUssQ0FBQyxHQUFXLEVBQUUsR0FBVyxFQUFFLEtBQWE7SUFDckQsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQzVDLENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxJQUFZO0lBQzlCLE9BQU8sS0FBSyxDQUFDLENBQUMsRUFBRSxzQkFBVyxFQUFFLENBQUMsU0FBUyxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUNwRCxDQUFDO0FBUUQsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLEdBQUcsRUFBRTtJQUNqQyxJQUFJLFFBQTJCLENBQUM7SUFDaEMsT0FBTyxHQUFHLEVBQUU7UUFDWCxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2QsUUFBUSxHQUFHLENBQUMsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNqRCxLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQyxXQUFXLENBQUMsRUFBRTtnQkFDbkUsTUFBTSxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBRSxDQUFDO2dCQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFO29CQUNqQixRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLE9BQXNCLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztpQkFDekQ7YUFDRDtTQUNEO1FBQ0QsT0FBTyxRQUFRLENBQUM7SUFDakIsQ0FBQyxDQUFDO0FBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUVMOzs7OztHQUtHO0FBQ0gsU0FBZ0Isd0JBQXdCLENBQUMsVUFBa0I7SUFDMUQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUMxQyxNQUFNLEtBQUssR0FBRyxtQkFBbUIsRUFBRSxDQUFDO0lBQ3BDLElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUM7SUFDaEMsS0FBSyxNQUFNLEtBQUssSUFBSSxLQUFLLEVBQUU7UUFDMUIsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFVBQVUsRUFBRTtZQUM5QixPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUM7U0FDNUM7YUFBTSxJQUFJLEtBQUssQ0FBQyxJQUFJLEdBQUcsVUFBVSxFQUFFO1lBQ25DLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDO1NBQ2pDO1FBQ0QsUUFBUSxHQUFHLEtBQUssQ0FBQztLQUNqQjtJQUNELE9BQU8sRUFBRSxRQUFRLEVBQUUsQ0FBQztBQUNyQixDQUFDO0FBYkQsNERBYUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLDJCQUEyQixDQUFDLE1BQWM7SUFDekQsTUFBTSxLQUFLLEdBQUcsbUJBQW1CLEVBQUUsQ0FBQztJQUNwQyxNQUFNLFFBQVEsR0FBRyxNQUFNLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQztJQUN6QyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNaLElBQUksRUFBRSxHQUFHLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQzFCLE9BQU8sRUFBRSxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUU7UUFDbkIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN0QyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDMUQsSUFBSSxNQUFNLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQyxNQUFNLElBQUksUUFBUSxFQUFFO1lBQzNDLEVBQUUsR0FBRyxHQUFHLENBQUM7U0FDVDthQUNJO1lBQ0osRUFBRSxHQUFHLEdBQUcsQ0FBQztTQUNUO0tBQ0Q7SUFDRCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDNUIsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO0lBQzNELElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxRQUFRLENBQUMsR0FBRyxHQUFHLFFBQVEsRUFBRTtRQUN2QyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUIsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDO0tBQ2hEO0lBQ0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsQ0FBQztBQUNoQyxDQUFDO0FBdEJELGtFQXNCQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0Isd0JBQXdCLENBQUMsSUFBWTtJQUNwRCxJQUFJLENBQUMsc0JBQVcsRUFBRSxDQUFDLHVCQUF1QixFQUFFO1FBQzNDLE9BQU87S0FDUDtJQUVELElBQUksSUFBSSxJQUFJLENBQUMsRUFBRTtRQUNkLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNqQyxPQUFPO0tBQ1A7SUFFRCxNQUFNLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxHQUFHLHdCQUF3QixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFELElBQUksQ0FBQyxRQUFRLEVBQUU7UUFDZCxPQUFPO0tBQ1A7SUFDRCxJQUFJLFFBQVEsR0FBRyxDQUFDLENBQUM7SUFDakIsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO0lBQ3RELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUM7SUFDN0IsSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxRQUFRLENBQUMsSUFBSSxFQUFFO1FBQ3hDLDhEQUE4RDtRQUM5RCxNQUFNLGVBQWUsR0FBRyxDQUFDLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3RSxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFLENBQUMsR0FBRyxHQUFHLFdBQVcsQ0FBQztRQUM3RSxRQUFRLEdBQUcsV0FBVyxHQUFHLGVBQWUsR0FBRyxhQUFhLENBQUM7S0FDekQ7U0FBTTtRQUNOLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEQsUUFBUSxHQUFHLFdBQVcsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsaUJBQWlCLENBQUMsQ0FBQztLQUMzRDtJQUNELE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsT0FBTyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUM7QUFDdkUsQ0FBQztBQTNCRCw0REEyQkM7QUFFRCxTQUFnQixnQ0FBZ0MsQ0FBQyxNQUFjO0lBQzlELE1BQU0sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEdBQUcsMkJBQTJCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDL0QsSUFBSSxRQUFRLEVBQUU7UUFDYixNQUFNLGNBQWMsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDaEUsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsT0FBTyxHQUFHLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMxRSxJQUFJLElBQUksRUFBRTtZQUNULE1BQU0sdUJBQXVCLEdBQUcsa0JBQWtCLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFLENBQUMsR0FBRyxHQUFHLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNySCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxHQUFHLHVCQUF1QixHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkYsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDdkI7YUFDSTtZQUNKLE1BQU0scUJBQXFCLEdBQUcsa0JBQWtCLEdBQUcsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDM0UsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLElBQUksR0FBRyxxQkFBcUIsQ0FBQztZQUNuRCxPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUN2QjtLQUNEO0lBQ0QsT0FBTyxJQUFJLENBQUM7QUFDYixDQUFDO0FBakJELDRFQWlCQzs7Ozs7Ozs7Ozs7Ozs7QUN2SUQ7OztnR0FHZ0c7O0FBYWhHLElBQUksY0FBYyxHQUFnQyxTQUFTLENBQUM7QUFFNUQsU0FBZ0IsT0FBTyxDQUFTLEdBQVc7SUFDMUMsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO0lBQ3hFLElBQUksT0FBTyxFQUFFO1FBQ1osTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QyxJQUFJLElBQUksRUFBRTtZQUNULE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUN4QjtLQUNEO0lBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQywyQkFBMkIsR0FBRyxFQUFFLENBQUMsQ0FBQztBQUNuRCxDQUFDO0FBVkQsMEJBVUM7QUFFRCxTQUFnQixXQUFXO0lBQzFCLElBQUksY0FBYyxFQUFFO1FBQ25CLE9BQU8sY0FBYyxDQUFDO0tBQ3RCO0lBRUQsY0FBYyxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUMxQyxJQUFJLGNBQWMsRUFBRTtRQUNuQixPQUFPLGNBQWMsQ0FBQztLQUN0QjtJQUVELE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztBQUM1QyxDQUFDO0FBWEQsa0NBV0MiLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzQ29udGVudCI6WyIgXHQvLyBUaGUgbW9kdWxlIGNhY2hlXG4gXHR2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkge1xuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuIFx0XHR9XG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRpOiBtb2R1bGVJZCxcbiBcdFx0XHRsOiBmYWxzZSxcbiBcdFx0XHRleHBvcnRzOiB7fVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sID0gdHJ1ZTtcblxuIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gXHR9XG5cblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlIGNhY2hlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbiBcdFx0XHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbiBcdFx0XHR9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuIFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcblxuXG4gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbiBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IFwiLi9wcmV2aWV3LXNyYy9pbmRleC50c1wiKTtcbiIsIi8qKlxuICogbG9kYXNoIChDdXN0b20gQnVpbGQpIDxodHRwczovL2xvZGFzaC5jb20vPlxuICogQnVpbGQ6IGBsb2Rhc2ggbW9kdWxhcml6ZSBleHBvcnRzPVwibnBtXCIgLW8gLi9gXG4gKiBDb3B5cmlnaHQgalF1ZXJ5IEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9ycyA8aHR0cHM6Ly9qcXVlcnkub3JnLz5cbiAqIFJlbGVhc2VkIHVuZGVyIE1JVCBsaWNlbnNlIDxodHRwczovL2xvZGFzaC5jb20vbGljZW5zZT5cbiAqIEJhc2VkIG9uIFVuZGVyc2NvcmUuanMgMS44LjMgPGh0dHA6Ly91bmRlcnNjb3JlanMub3JnL0xJQ0VOU0U+XG4gKiBDb3B5cmlnaHQgSmVyZW15IEFzaGtlbmFzLCBEb2N1bWVudENsb3VkIGFuZCBJbnZlc3RpZ2F0aXZlIFJlcG9ydGVycyAmIEVkaXRvcnNcbiAqL1xuXG4vKiogVXNlZCBhcyB0aGUgYFR5cGVFcnJvcmAgbWVzc2FnZSBmb3IgXCJGdW5jdGlvbnNcIiBtZXRob2RzLiAqL1xudmFyIEZVTkNfRVJST1JfVEVYVCA9ICdFeHBlY3RlZCBhIGZ1bmN0aW9uJztcblxuLyoqIFVzZWQgYXMgcmVmZXJlbmNlcyBmb3IgdmFyaW91cyBgTnVtYmVyYCBjb25zdGFudHMuICovXG52YXIgTkFOID0gMCAvIDA7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBzeW1ib2xUYWcgPSAnW29iamVjdCBTeW1ib2xdJztcblxuLyoqIFVzZWQgdG8gbWF0Y2ggbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZS4gKi9cbnZhciByZVRyaW0gPSAvXlxccyt8XFxzKyQvZztcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IGJhZCBzaWduZWQgaGV4YWRlY2ltYWwgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzQmFkSGV4ID0gL15bLStdMHhbMC05YS1mXSskL2k7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBiaW5hcnkgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzQmluYXJ5ID0gL14wYlswMV0rJC9pO1xuXG4vKiogVXNlZCB0byBkZXRlY3Qgb2N0YWwgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzT2N0YWwgPSAvXjBvWzAtN10rJC9pO1xuXG4vKiogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgd2l0aG91dCBhIGRlcGVuZGVuY3kgb24gYHJvb3RgLiAqL1xudmFyIGZyZWVQYXJzZUludCA9IHBhcnNlSW50O1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzLiAqL1xudmFyIGZyZWVHbG9iYWwgPSB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbCAmJiBnbG9iYWwuT2JqZWN0ID09PSBPYmplY3QgJiYgZ2xvYmFsO1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYHNlbGZgLiAqL1xudmFyIGZyZWVTZWxmID0gdHlwZW9mIHNlbGYgPT0gJ29iamVjdCcgJiYgc2VsZiAmJiBzZWxmLk9iamVjdCA9PT0gT2JqZWN0ICYmIHNlbGY7XG5cbi8qKiBVc2VkIGFzIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0LiAqL1xudmFyIHJvb3QgPSBmcmVlR2xvYmFsIHx8IGZyZWVTZWxmIHx8IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKlxuICogVXNlZCB0byByZXNvbHZlIHRoZVxuICogW2B0b1N0cmluZ1RhZ2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmcpXG4gKiBvZiB2YWx1ZXMuXG4gKi9cbnZhciBvYmplY3RUb1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyBmb3IgdGhvc2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGFzIG90aGVyIGBsb2Rhc2hgIG1ldGhvZHMuICovXG52YXIgbmF0aXZlTWF4ID0gTWF0aC5tYXgsXG4gICAgbmF0aXZlTWluID0gTWF0aC5taW47XG5cbi8qKlxuICogR2V0cyB0aGUgdGltZXN0YW1wIG9mIHRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRoYXQgaGF2ZSBlbGFwc2VkIHNpbmNlXG4gKiB0aGUgVW5peCBlcG9jaCAoMSBKYW51YXJ5IDE5NzAgMDA6MDA6MDAgVVRDKS5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDIuNC4wXG4gKiBAY2F0ZWdvcnkgRGF0ZVxuICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdGltZXN0YW1wLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmRlZmVyKGZ1bmN0aW9uKHN0YW1wKSB7XG4gKiAgIGNvbnNvbGUubG9nKF8ubm93KCkgLSBzdGFtcCk7XG4gKiB9LCBfLm5vdygpKTtcbiAqIC8vID0+IExvZ3MgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgaXQgdG9vayBmb3IgdGhlIGRlZmVycmVkIGludm9jYXRpb24uXG4gKi9cbnZhciBub3cgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHJvb3QuRGF0ZS5ub3coKTtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlYm91bmNlZCBmdW5jdGlvbiB0aGF0IGRlbGF5cyBpbnZva2luZyBgZnVuY2AgdW50aWwgYWZ0ZXIgYHdhaXRgXG4gKiBtaWxsaXNlY29uZHMgaGF2ZSBlbGFwc2VkIHNpbmNlIHRoZSBsYXN0IHRpbWUgdGhlIGRlYm91bmNlZCBmdW5jdGlvbiB3YXNcbiAqIGludm9rZWQuIFRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gY29tZXMgd2l0aCBhIGBjYW5jZWxgIG1ldGhvZCB0byBjYW5jZWxcbiAqIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvIGltbWVkaWF0ZWx5IGludm9rZSB0aGVtLlxuICogUHJvdmlkZSBgb3B0aW9uc2AgdG8gaW5kaWNhdGUgd2hldGhlciBgZnVuY2Agc2hvdWxkIGJlIGludm9rZWQgb24gdGhlXG4gKiBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZSBgd2FpdGAgdGltZW91dC4gVGhlIGBmdW5jYCBpcyBpbnZva2VkXG4gKiB3aXRoIHRoZSBsYXN0IGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uLiBTdWJzZXF1ZW50XG4gKiBjYWxscyB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIHJldHVybiB0aGUgcmVzdWx0IG9mIHRoZSBsYXN0IGBmdW5jYFxuICogaW52b2NhdGlvbi5cbiAqXG4gKiAqKk5vdGU6KiogSWYgYGxlYWRpbmdgIGFuZCBgdHJhaWxpbmdgIG9wdGlvbnMgYXJlIGB0cnVlYCwgYGZ1bmNgIGlzXG4gKiBpbnZva2VkIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIGRlYm91bmNlZCBmdW5jdGlvblxuICogaXMgaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICpcbiAqIElmIGB3YWl0YCBpcyBgMGAgYW5kIGBsZWFkaW5nYCBpcyBgZmFsc2VgLCBgZnVuY2AgaW52b2NhdGlvbiBpcyBkZWZlcnJlZFxuICogdW50aWwgdG8gdGhlIG5leHQgdGljaywgc2ltaWxhciB0byBgc2V0VGltZW91dGAgd2l0aCBhIHRpbWVvdXQgb2YgYDBgLlxuICpcbiAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwczovL2Nzcy10cmlja3MuY29tL2RlYm91bmNpbmctdGhyb3R0bGluZy1leHBsYWluZWQtZXhhbXBsZXMvKVxuICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy5kZWJvdW5jZWAgYW5kIGBfLnRocm90dGxlYC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlYm91bmNlLlxuICogQHBhcmFtIHtudW1iZXJ9IFt3YWl0PTBdIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIGRlbGF5LlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9ZmFsc2VdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgbGVhZGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLm1heFdhaXRdXG4gKiAgVGhlIG1heGltdW0gdGltZSBgZnVuY2AgaXMgYWxsb3dlZCB0byBiZSBkZWxheWVkIGJlZm9yZSBpdCdzIGludm9rZWQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLnRyYWlsaW5nPXRydWVdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGRlYm91bmNlZCBmdW5jdGlvbi5cbiAqIEBleGFtcGxlXG4gKlxuICogLy8gQXZvaWQgY29zdGx5IGNhbGN1bGF0aW9ucyB3aGlsZSB0aGUgd2luZG93IHNpemUgaXMgaW4gZmx1eC5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdyZXNpemUnLCBfLmRlYm91bmNlKGNhbGN1bGF0ZUxheW91dCwgMTUwKSk7XG4gKlxuICogLy8gSW52b2tlIGBzZW5kTWFpbGAgd2hlbiBjbGlja2VkLCBkZWJvdW5jaW5nIHN1YnNlcXVlbnQgY2FsbHMuXG4gKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgXy5kZWJvdW5jZShzZW5kTWFpbCwgMzAwLCB7XG4gKiAgICdsZWFkaW5nJzogdHJ1ZSxcbiAqICAgJ3RyYWlsaW5nJzogZmFsc2VcbiAqIH0pKTtcbiAqXG4gKiAvLyBFbnN1cmUgYGJhdGNoTG9nYCBpcyBpbnZva2VkIG9uY2UgYWZ0ZXIgMSBzZWNvbmQgb2YgZGVib3VuY2VkIGNhbGxzLlxuICogdmFyIGRlYm91bmNlZCA9IF8uZGVib3VuY2UoYmF0Y2hMb2csIDI1MCwgeyAnbWF4V2FpdCc6IDEwMDAgfSk7XG4gKiB2YXIgc291cmNlID0gbmV3IEV2ZW50U291cmNlKCcvc3RyZWFtJyk7XG4gKiBqUXVlcnkoc291cmNlKS5vbignbWVzc2FnZScsIGRlYm91bmNlZCk7XG4gKlxuICogLy8gQ2FuY2VsIHRoZSB0cmFpbGluZyBkZWJvdW5jZWQgaW52b2NhdGlvbi5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdwb3BzdGF0ZScsIGRlYm91bmNlZC5jYW5jZWwpO1xuICovXG5mdW5jdGlvbiBkZWJvdW5jZShmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gIHZhciBsYXN0QXJncyxcbiAgICAgIGxhc3RUaGlzLFxuICAgICAgbWF4V2FpdCxcbiAgICAgIHJlc3VsdCxcbiAgICAgIHRpbWVySWQsXG4gICAgICBsYXN0Q2FsbFRpbWUsXG4gICAgICBsYXN0SW52b2tlVGltZSA9IDAsXG4gICAgICBsZWFkaW5nID0gZmFsc2UsXG4gICAgICBtYXhpbmcgPSBmYWxzZSxcbiAgICAgIHRyYWlsaW5nID0gdHJ1ZTtcblxuICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgfVxuICB3YWl0ID0gdG9OdW1iZXIod2FpdCkgfHwgMDtcbiAgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgbGVhZGluZyA9ICEhb3B0aW9ucy5sZWFkaW5nO1xuICAgIG1heGluZyA9ICdtYXhXYWl0JyBpbiBvcHRpb25zO1xuICAgIG1heFdhaXQgPSBtYXhpbmcgPyBuYXRpdmVNYXgodG9OdW1iZXIob3B0aW9ucy5tYXhXYWl0KSB8fCAwLCB3YWl0KSA6IG1heFdhaXQ7XG4gICAgdHJhaWxpbmcgPSAndHJhaWxpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMudHJhaWxpbmcgOiB0cmFpbGluZztcbiAgfVxuXG4gIGZ1bmN0aW9uIGludm9rZUZ1bmModGltZSkge1xuICAgIHZhciBhcmdzID0gbGFzdEFyZ3MsXG4gICAgICAgIHRoaXNBcmcgPSBsYXN0VGhpcztcblxuICAgIGxhc3RBcmdzID0gbGFzdFRoaXMgPSB1bmRlZmluZWQ7XG4gICAgbGFzdEludm9rZVRpbWUgPSB0aW1lO1xuICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpc0FyZywgYXJncyk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGxlYWRpbmdFZGdlKHRpbWUpIHtcbiAgICAvLyBSZXNldCBhbnkgYG1heFdhaXRgIHRpbWVyLlxuICAgIGxhc3RJbnZva2VUaW1lID0gdGltZTtcbiAgICAvLyBTdGFydCB0aGUgdGltZXIgZm9yIHRoZSB0cmFpbGluZyBlZGdlLlxuICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgd2FpdCk7XG4gICAgLy8gSW52b2tlIHRoZSBsZWFkaW5nIGVkZ2UuXG4gICAgcmV0dXJuIGxlYWRpbmcgPyBpbnZva2VGdW5jKHRpbWUpIDogcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtYWluaW5nV2FpdCh0aW1lKSB7XG4gICAgdmFyIHRpbWVTaW5jZUxhc3RDYWxsID0gdGltZSAtIGxhc3RDYWxsVGltZSxcbiAgICAgICAgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZSxcbiAgICAgICAgcmVzdWx0ID0gd2FpdCAtIHRpbWVTaW5jZUxhc3RDYWxsO1xuXG4gICAgcmV0dXJuIG1heGluZyA/IG5hdGl2ZU1pbihyZXN1bHQsIG1heFdhaXQgLSB0aW1lU2luY2VMYXN0SW52b2tlKSA6IHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNob3VsZEludm9rZSh0aW1lKSB7XG4gICAgdmFyIHRpbWVTaW5jZUxhc3RDYWxsID0gdGltZSAtIGxhc3RDYWxsVGltZSxcbiAgICAgICAgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZTtcblxuICAgIC8vIEVpdGhlciB0aGlzIGlzIHRoZSBmaXJzdCBjYWxsLCBhY3Rpdml0eSBoYXMgc3RvcHBlZCBhbmQgd2UncmUgYXQgdGhlXG4gICAgLy8gdHJhaWxpbmcgZWRnZSwgdGhlIHN5c3RlbSB0aW1lIGhhcyBnb25lIGJhY2t3YXJkcyBhbmQgd2UncmUgdHJlYXRpbmdcbiAgICAvLyBpdCBhcyB0aGUgdHJhaWxpbmcgZWRnZSwgb3Igd2UndmUgaGl0IHRoZSBgbWF4V2FpdGAgbGltaXQuXG4gICAgcmV0dXJuIChsYXN0Q2FsbFRpbWUgPT09IHVuZGVmaW5lZCB8fCAodGltZVNpbmNlTGFzdENhbGwgPj0gd2FpdCkgfHxcbiAgICAgICh0aW1lU2luY2VMYXN0Q2FsbCA8IDApIHx8IChtYXhpbmcgJiYgdGltZVNpbmNlTGFzdEludm9rZSA+PSBtYXhXYWl0KSk7XG4gIH1cblxuICBmdW5jdGlvbiB0aW1lckV4cGlyZWQoKSB7XG4gICAgdmFyIHRpbWUgPSBub3coKTtcbiAgICBpZiAoc2hvdWxkSW52b2tlKHRpbWUpKSB7XG4gICAgICByZXR1cm4gdHJhaWxpbmdFZGdlKHRpbWUpO1xuICAgIH1cbiAgICAvLyBSZXN0YXJ0IHRoZSB0aW1lci5cbiAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHJlbWFpbmluZ1dhaXQodGltZSkpO1xuICB9XG5cbiAgZnVuY3Rpb24gdHJhaWxpbmdFZGdlKHRpbWUpIHtcbiAgICB0aW1lcklkID0gdW5kZWZpbmVkO1xuXG4gICAgLy8gT25seSBpbnZva2UgaWYgd2UgaGF2ZSBgbGFzdEFyZ3NgIHdoaWNoIG1lYW5zIGBmdW5jYCBoYXMgYmVlblxuICAgIC8vIGRlYm91bmNlZCBhdCBsZWFzdCBvbmNlLlxuICAgIGlmICh0cmFpbGluZyAmJiBsYXN0QXJncykge1xuICAgICAgcmV0dXJuIGludm9rZUZ1bmModGltZSk7XG4gICAgfVxuICAgIGxhc3RBcmdzID0gbGFzdFRoaXMgPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbmNlbCgpIHtcbiAgICBpZiAodGltZXJJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXJJZCk7XG4gICAgfVxuICAgIGxhc3RJbnZva2VUaW1lID0gMDtcbiAgICBsYXN0QXJncyA9IGxhc3RDYWxsVGltZSA9IGxhc3RUaGlzID0gdGltZXJJZCA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZsdXNoKCkge1xuICAgIHJldHVybiB0aW1lcklkID09PSB1bmRlZmluZWQgPyByZXN1bHQgOiB0cmFpbGluZ0VkZ2Uobm93KCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gZGVib3VuY2VkKCkge1xuICAgIHZhciB0aW1lID0gbm93KCksXG4gICAgICAgIGlzSW52b2tpbmcgPSBzaG91bGRJbnZva2UodGltZSk7XG5cbiAgICBsYXN0QXJncyA9IGFyZ3VtZW50cztcbiAgICBsYXN0VGhpcyA9IHRoaXM7XG4gICAgbGFzdENhbGxUaW1lID0gdGltZTtcblxuICAgIGlmIChpc0ludm9raW5nKSB7XG4gICAgICBpZiAodGltZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBsZWFkaW5nRWRnZShsYXN0Q2FsbFRpbWUpO1xuICAgICAgfVxuICAgICAgaWYgKG1heGluZykge1xuICAgICAgICAvLyBIYW5kbGUgaW52b2NhdGlvbnMgaW4gYSB0aWdodCBsb29wLlxuICAgICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgICAgICByZXR1cm4gaW52b2tlRnVuYyhsYXN0Q2FsbFRpbWUpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAodGltZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIGRlYm91bmNlZC5jYW5jZWwgPSBjYW5jZWw7XG4gIGRlYm91bmNlZC5mbHVzaCA9IGZsdXNoO1xuICByZXR1cm4gZGVib3VuY2VkO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSB0aHJvdHRsZWQgZnVuY3Rpb24gdGhhdCBvbmx5IGludm9rZXMgYGZ1bmNgIGF0IG1vc3Qgb25jZSBwZXJcbiAqIGV2ZXJ5IGB3YWl0YCBtaWxsaXNlY29uZHMuIFRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gY29tZXMgd2l0aCBhIGBjYW5jZWxgXG4gKiBtZXRob2QgdG8gY2FuY2VsIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvXG4gKiBpbW1lZGlhdGVseSBpbnZva2UgdGhlbS4gUHJvdmlkZSBgb3B0aW9uc2AgdG8gaW5kaWNhdGUgd2hldGhlciBgZnVuY2BcbiAqIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZSBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZSBgd2FpdGBcbiAqIHRpbWVvdXQuIFRoZSBgZnVuY2AgaXMgaW52b2tlZCB3aXRoIHRoZSBsYXN0IGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGVcbiAqIHRocm90dGxlZCBmdW5jdGlvbi4gU3Vic2VxdWVudCBjYWxscyB0byB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uIHJldHVybiB0aGVcbiAqIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2AgaW52b2NhdGlvbi5cbiAqXG4gKiAqKk5vdGU6KiogSWYgYGxlYWRpbmdgIGFuZCBgdHJhaWxpbmdgIG9wdGlvbnMgYXJlIGB0cnVlYCwgYGZ1bmNgIGlzXG4gKiBpbnZva2VkIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIHRocm90dGxlZCBmdW5jdGlvblxuICogaXMgaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICpcbiAqIElmIGB3YWl0YCBpcyBgMGAgYW5kIGBsZWFkaW5nYCBpcyBgZmFsc2VgLCBgZnVuY2AgaW52b2NhdGlvbiBpcyBkZWZlcnJlZFxuICogdW50aWwgdG8gdGhlIG5leHQgdGljaywgc2ltaWxhciB0byBgc2V0VGltZW91dGAgd2l0aCBhIHRpbWVvdXQgb2YgYDBgLlxuICpcbiAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwczovL2Nzcy10cmlja3MuY29tL2RlYm91bmNpbmctdGhyb3R0bGluZy1leHBsYWluZWQtZXhhbXBsZXMvKVxuICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy50aHJvdHRsZWAgYW5kIGBfLmRlYm91bmNlYC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHRocm90dGxlLlxuICogQHBhcmFtIHtudW1iZXJ9IFt3YWl0PTBdIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIHRocm90dGxlIGludm9jYXRpb25zIHRvLlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9dHJ1ZV1cbiAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSBsZWFkaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLnRyYWlsaW5nPXRydWVdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHRocm90dGxlZCBmdW5jdGlvbi5cbiAqIEBleGFtcGxlXG4gKlxuICogLy8gQXZvaWQgZXhjZXNzaXZlbHkgdXBkYXRpbmcgdGhlIHBvc2l0aW9uIHdoaWxlIHNjcm9sbGluZy5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdzY3JvbGwnLCBfLnRocm90dGxlKHVwZGF0ZVBvc2l0aW9uLCAxMDApKTtcbiAqXG4gKiAvLyBJbnZva2UgYHJlbmV3VG9rZW5gIHdoZW4gdGhlIGNsaWNrIGV2ZW50IGlzIGZpcmVkLCBidXQgbm90IG1vcmUgdGhhbiBvbmNlIGV2ZXJ5IDUgbWludXRlcy5cbiAqIHZhciB0aHJvdHRsZWQgPSBfLnRocm90dGxlKHJlbmV3VG9rZW4sIDMwMDAwMCwgeyAndHJhaWxpbmcnOiBmYWxzZSB9KTtcbiAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCB0aHJvdHRsZWQpO1xuICpcbiAqIC8vIENhbmNlbCB0aGUgdHJhaWxpbmcgdGhyb3R0bGVkIGludm9jYXRpb24uXG4gKiBqUXVlcnkod2luZG93KS5vbigncG9wc3RhdGUnLCB0aHJvdHRsZWQuY2FuY2VsKTtcbiAqL1xuZnVuY3Rpb24gdGhyb3R0bGUoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICB2YXIgbGVhZGluZyA9IHRydWUsXG4gICAgICB0cmFpbGluZyA9IHRydWU7XG5cbiAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gIH1cbiAgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgbGVhZGluZyA9ICdsZWFkaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLmxlYWRpbmcgOiBsZWFkaW5nO1xuICAgIHRyYWlsaW5nID0gJ3RyYWlsaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLnRyYWlsaW5nIDogdHJhaWxpbmc7XG4gIH1cbiAgcmV0dXJuIGRlYm91bmNlKGZ1bmMsIHdhaXQsIHtcbiAgICAnbGVhZGluZyc6IGxlYWRpbmcsXG4gICAgJ21heFdhaXQnOiB3YWl0LFxuICAgICd0cmFpbGluZyc6IHRyYWlsaW5nXG4gIH0pO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIHRoZVxuICogW2xhbmd1YWdlIHR5cGVdKGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1lY21hc2NyaXB0LWxhbmd1YWdlLXR5cGVzKVxuICogb2YgYE9iamVjdGAuIChlLmcuIGFycmF5cywgZnVuY3Rpb25zLCBvYmplY3RzLCByZWdleGVzLCBgbmV3IE51bWJlcigwKWAsIGFuZCBgbmV3IFN0cmluZygnJylgKVxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzT2JqZWN0KHt9KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChfLm5vb3ApO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcbiAgcmV0dXJuICEhdmFsdWUgJiYgKHR5cGUgPT0gJ29iamVjdCcgfHwgdHlwZSA9PSAnZnVuY3Rpb24nKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZS4gQSB2YWx1ZSBpcyBvYmplY3QtbGlrZSBpZiBpdCdzIG5vdCBgbnVsbGBcbiAqIGFuZCBoYXMgYSBgdHlwZW9mYCByZXN1bHQgb2YgXCJvYmplY3RcIi5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZSwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZSh7fSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdExpa2UoWzEsIDIsIDNdKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShfLm5vb3ApO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShudWxsKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzT2JqZWN0TGlrZSh2YWx1ZSkge1xuICByZXR1cm4gISF2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCc7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBTeW1ib2xgIHByaW1pdGl2ZSBvciBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBzeW1ib2wsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc1N5bWJvbChTeW1ib2wuaXRlcmF0b3IpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNTeW1ib2woJ2FiYycpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNTeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnc3ltYm9sJyB8fFxuICAgIChpc09iamVjdExpa2UodmFsdWUpICYmIG9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpID09IHN5bWJvbFRhZyk7XG59XG5cbi8qKlxuICogQ29udmVydHMgYHZhbHVlYCB0byBhIG51bWJlci5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvY2Vzcy5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIG51bWJlci5cbiAqIEBleGFtcGxlXG4gKlxuICogXy50b051bWJlcigzLjIpO1xuICogLy8gPT4gMy4yXG4gKlxuICogXy50b051bWJlcihOdW1iZXIuTUlOX1ZBTFVFKTtcbiAqIC8vID0+IDVlLTMyNFxuICpcbiAqIF8udG9OdW1iZXIoSW5maW5pdHkpO1xuICogLy8gPT4gSW5maW5pdHlcbiAqXG4gKiBfLnRvTnVtYmVyKCczLjInKTtcbiAqIC8vID0+IDMuMlxuICovXG5mdW5jdGlvbiB0b051bWJlcih2YWx1ZSkge1xuICBpZiAodHlwZW9mIHZhbHVlID09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG4gIGlmIChpc1N5bWJvbCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gTkFOO1xuICB9XG4gIGlmIChpc09iamVjdCh2YWx1ZSkpIHtcbiAgICB2YXIgb3RoZXIgPSB0eXBlb2YgdmFsdWUudmFsdWVPZiA9PSAnZnVuY3Rpb24nID8gdmFsdWUudmFsdWVPZigpIDogdmFsdWU7XG4gICAgdmFsdWUgPSBpc09iamVjdChvdGhlcikgPyAob3RoZXIgKyAnJykgOiBvdGhlcjtcbiAgfVxuICBpZiAodHlwZW9mIHZhbHVlICE9ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHZhbHVlID09PSAwID8gdmFsdWUgOiArdmFsdWU7XG4gIH1cbiAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKHJlVHJpbSwgJycpO1xuICB2YXIgaXNCaW5hcnkgPSByZUlzQmluYXJ5LnRlc3QodmFsdWUpO1xuICByZXR1cm4gKGlzQmluYXJ5IHx8IHJlSXNPY3RhbC50ZXN0KHZhbHVlKSlcbiAgICA/IGZyZWVQYXJzZUludCh2YWx1ZS5zbGljZSgyKSwgaXNCaW5hcnkgPyAyIDogOClcbiAgICA6IChyZUlzQmFkSGV4LnRlc3QodmFsdWUpID8gTkFOIDogK3ZhbHVlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB0aHJvdHRsZTtcbiIsInZhciBnO1xyXG5cclxuLy8gVGhpcyB3b3JrcyBpbiBub24tc3RyaWN0IG1vZGVcclxuZyA9IChmdW5jdGlvbigpIHtcclxuXHRyZXR1cm4gdGhpcztcclxufSkoKTtcclxuXHJcbnRyeSB7XHJcblx0Ly8gVGhpcyB3b3JrcyBpZiBldmFsIGlzIGFsbG93ZWQgKHNlZSBDU1ApXHJcblx0ZyA9IGcgfHwgRnVuY3Rpb24oXCJyZXR1cm4gdGhpc1wiKSgpIHx8ICgxLCBldmFsKShcInRoaXNcIik7XHJcbn0gY2F0Y2ggKGUpIHtcclxuXHQvLyBUaGlzIHdvcmtzIGlmIHRoZSB3aW5kb3cgcmVmZXJlbmNlIGlzIGF2YWlsYWJsZVxyXG5cdGlmICh0eXBlb2Ygd2luZG93ID09PSBcIm9iamVjdFwiKSBnID0gd2luZG93O1xyXG59XHJcblxyXG4vLyBnIGNhbiBzdGlsbCBiZSB1bmRlZmluZWQsIGJ1dCBub3RoaW5nIHRvIGRvIGFib3V0IGl0Li4uXHJcbi8vIFdlIHJldHVybiB1bmRlZmluZWQsIGluc3RlYWQgb2Ygbm90aGluZyBoZXJlLCBzbyBpdCdzXHJcbi8vIGVhc2llciB0byBoYW5kbGUgdGhpcyBjYXNlLiBpZighZ2xvYmFsKSB7IC4uLn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZztcclxuIiwiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5pbXBvcnQgeyBnZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUgfSBmcm9tICcuL3Njcm9sbC1zeW5jJztcblxuZXhwb3J0IGNsYXNzIEFjdGl2ZUxpbmVNYXJrZXIge1xuXHRwcml2YXRlIF9jdXJyZW50OiBhbnk7XG5cblx0b25EaWRDaGFuZ2VUZXh0RWRpdG9yU2VsZWN0aW9uKGxpbmU6IG51bWJlcikge1xuXHRcdGNvbnN0IHsgcHJldmlvdXMgfSA9IGdldEVsZW1lbnRzRm9yU291cmNlTGluZShsaW5lKTtcblx0XHR0aGlzLl91cGRhdGUocHJldmlvdXMgJiYgcHJldmlvdXMuZWxlbWVudCk7XG5cdH1cblxuXHRfdXBkYXRlKGJlZm9yZTogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQpIHtcblx0XHR0aGlzLl91bm1hcmtBY3RpdmVFbGVtZW50KHRoaXMuX2N1cnJlbnQpO1xuXHRcdHRoaXMuX21hcmtBY3RpdmVFbGVtZW50KGJlZm9yZSk7XG5cdFx0dGhpcy5fY3VycmVudCA9IGJlZm9yZTtcblx0fVxuXG5cdF91bm1hcmtBY3RpdmVFbGVtZW50KGVsZW1lbnQ6IEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkKSB7XG5cdFx0aWYgKCFlbGVtZW50KSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGVsZW1lbnQuY2xhc3NOYW1lID0gZWxlbWVudC5jbGFzc05hbWUucmVwbGFjZSgvXFxiY29kZS1hY3RpdmUtbGluZVxcYi9nLCAnJyk7XG5cdH1cblxuXHRfbWFya0FjdGl2ZUVsZW1lbnQoZWxlbWVudDogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQpIHtcblx0XHRpZiAoIWVsZW1lbnQpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0ZWxlbWVudC5jbGFzc05hbWUgKz0gJyBjb2RlLWFjdGl2ZS1saW5lJztcblx0fVxufSIsIi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5leHBvcnQgZnVuY3Rpb24gb25jZURvY3VtZW50TG9hZGVkKGY6ICgpID0+IHZvaWQpIHtcblx0aWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdsb2FkaW5nJyB8fCBkb2N1bWVudC5yZWFkeVN0YXRlIGFzIHN0cmluZyA9PT0gJ3VuaW5pdGlhbGl6ZWQnKSB7XG5cdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGYpO1xuXHR9IGVsc2Uge1xuXHRcdGYoKTtcblx0fVxufSIsIi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5pbXBvcnQgeyBBY3RpdmVMaW5lTWFya2VyIH0gZnJvbSAnLi9hY3RpdmVMaW5lTWFya2VyJztcbmltcG9ydCB7IG9uY2VEb2N1bWVudExvYWRlZCB9IGZyb20gJy4vZXZlbnRzJztcbmltcG9ydCB7IGNyZWF0ZVBvc3RlckZvclZzQ29kZSB9IGZyb20gJy4vbWVzc2FnaW5nJztcbmltcG9ydCB7IGdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0LCBzY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUgfSBmcm9tICcuL3Njcm9sbC1zeW5jJztcbmltcG9ydCB7IGdldFNldHRpbmdzLCBnZXREYXRhIH0gZnJvbSAnLi9zZXR0aW5ncyc7XG5pbXBvcnQgdGhyb3R0bGUgPSByZXF1aXJlKCdsb2Rhc2gudGhyb3R0bGUnKTtcblxuZGVjbGFyZSB2YXIgYWNxdWlyZVZzQ29kZUFwaTogYW55O1xuXG5sZXQgc2Nyb2xsRGlzYWJsZWQgPSB0cnVlO1xuY29uc3QgbWFya2VyID0gbmV3IEFjdGl2ZUxpbmVNYXJrZXIoKTtcbmNvbnN0IHNldHRpbmdzID0gZ2V0U2V0dGluZ3MoKTtcblxuY29uc3QgdnNjb2RlID0gYWNxdWlyZVZzQ29kZUFwaSgpO1xuXG4vLyBTZXQgVlMgQ29kZSBzdGF0ZVxubGV0IHN0YXRlID0gZ2V0RGF0YTx7IGxpbmU6IG51bWJlciB9PignZGF0YS1zdGF0ZScpO1xudnNjb2RlLnNldFN0YXRlKHN0YXRlKTtcblxuY29uc3QgbWVzc2FnaW5nID0gY3JlYXRlUG9zdGVyRm9yVnNDb2RlKHZzY29kZSk7XG5cbndpbmRvdy5jc3BBbGVydGVyLnNldFBvc3RlcihtZXNzYWdpbmcpO1xud2luZG93LnN0eWxlTG9hZGluZ01vbml0b3Iuc2V0UG9zdGVyKG1lc3NhZ2luZyk7XG5cbndpbmRvdy5vbmxvYWQgPSAoKSA9PiB7XG5cdHVwZGF0ZUltYWdlU2l6ZXMoKTtcbn07XG5cbm9uY2VEb2N1bWVudExvYWRlZCgoKSA9PiB7XG5cdGlmIChzZXR0aW5ncy5zY3JvbGxQcmV2aWV3V2l0aEVkaXRvcikge1xuXHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0Y29uc3QgaW5pdGlhbExpbmUgPSArc2V0dGluZ3MubGluZTtcblx0XHRcdGlmICghaXNOYU4oaW5pdGlhbExpbmUpKSB7XG5cdFx0XHRcdHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcblx0XHRcdFx0c2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lKGluaXRpYWxMaW5lKTtcblx0XHRcdH1cblx0XHR9LCAwKTtcblx0fVxufSk7XG5cbmNvbnN0IG9uVXBkYXRlVmlldyA9ICgoKSA9PiB7XG5cdGNvbnN0IGRvU2Nyb2xsID0gdGhyb3R0bGUoKGxpbmU6IG51bWJlcikgPT4ge1xuXHRcdHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcblx0XHRzY3JvbGxUb1JldmVhbFNvdXJjZUxpbmUobGluZSk7XG5cdH0sIDUwKTtcblxuXHRyZXR1cm4gKGxpbmU6IG51bWJlciwgc2V0dGluZ3M6IGFueSkgPT4ge1xuXHRcdGlmICghaXNOYU4obGluZSkpIHtcblx0XHRcdHNldHRpbmdzLmxpbmUgPSBsaW5lO1xuXHRcdFx0ZG9TY3JvbGwobGluZSk7XG5cdFx0fVxuXHR9O1xufSkoKTtcblxubGV0IHVwZGF0ZUltYWdlU2l6ZXMgPSB0aHJvdHRsZSgoKSA9PiB7XG5cdGNvbnN0IGltYWdlSW5mbzogeyBpZDogc3RyaW5nLCBoZWlnaHQ6IG51bWJlciwgd2lkdGg6IG51bWJlciB9W10gPSBbXTtcblx0bGV0IGltYWdlcyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdpbWcnKTtcblx0aWYgKGltYWdlcykge1xuXHRcdGxldCBpO1xuXHRcdGZvciAoaSA9IDA7IGkgPCBpbWFnZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IGltZyA9IGltYWdlc1tpXTtcblxuXHRcdFx0aWYgKGltZy5jbGFzc0xpc3QuY29udGFpbnMoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHRpbWcuY2xhc3NMaXN0LnJlbW92ZSgnbG9hZGluZycpO1xuXHRcdFx0fVxuXG5cdFx0XHRpbWFnZUluZm8ucHVzaCh7XG5cdFx0XHRcdGlkOiBpbWcuaWQsXG5cdFx0XHRcdGhlaWdodDogaW1nLmhlaWdodCxcblx0XHRcdFx0d2lkdGg6IGltZy53aWR0aFxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0bWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdjYWNoZUltYWdlU2l6ZXMnLCBpbWFnZUluZm8pO1xuXHR9XG59LCA1MCk7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCAoKSA9PiB7XG5cdHNjcm9sbERpc2FibGVkID0gdHJ1ZTtcblx0dXBkYXRlSW1hZ2VTaXplcygpO1xufSwgdHJ1ZSk7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZXZlbnQgPT4ge1xuXHRpZiAoZXZlbnQuZGF0YS5zb3VyY2UgIT09IHNldHRpbmdzLnNvdXJjZSkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdHN3aXRjaCAoZXZlbnQuZGF0YS50eXBlKSB7XG5cdFx0Y2FzZSAnb25EaWRDaGFuZ2VUZXh0RWRpdG9yU2VsZWN0aW9uJzpcblx0XHRcdG1hcmtlci5vbkRpZENoYW5nZVRleHRFZGl0b3JTZWxlY3Rpb24oZXZlbnQuZGF0YS5saW5lKTtcblx0XHRcdGJyZWFrO1xuXG5cdFx0Y2FzZSAndXBkYXRlVmlldyc6XG5cdFx0XHRvblVwZGF0ZVZpZXcoZXZlbnQuZGF0YS5saW5lLCBzZXR0aW5ncyk7XG5cdFx0XHRicmVhaztcblx0fVxufSwgZmFsc2UpO1xuXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIGV2ZW50ID0+IHtcblx0aWYgKCFzZXR0aW5ncy5kb3VibGVDbGlja1RvU3dpdGNoVG9FZGl0b3IpIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHQvLyBJZ25vcmUgY2xpY2tzIG9uIGxpbmtzXG5cdGZvciAobGV0IG5vZGUgPSBldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7IG5vZGU7IG5vZGUgPSBub2RlLnBhcmVudE5vZGUgYXMgSFRNTEVsZW1lbnQpIHtcblx0XHRpZiAobm9kZS50YWdOYW1lID09PSAnQScpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdH1cblxuXHRjb25zdCBvZmZzZXQgPSBldmVudC5wYWdlWTtcblx0Y29uc3QgbGluZSA9IGdldEVkaXRvckxpbmVOdW1iZXJGb3JQYWdlT2Zmc2V0KG9mZnNldCk7XG5cdGlmICh0eXBlb2YgbGluZSA9PT0gJ251bWJlcicgJiYgIWlzTmFOKGxpbmUpKSB7XG5cdFx0bWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdkaWRDbGljaycsIHsgbGluZTogTWF0aC5mbG9vcihsaW5lKSB9KTtcblx0fVxufSk7XG5cbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZXZlbnQgPT4ge1xuXHRpZiAoIWV2ZW50KSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0bGV0IG5vZGU6IGFueSA9IGV2ZW50LnRhcmdldDtcblx0d2hpbGUgKG5vZGUpIHtcblx0XHRpZiAobm9kZS50YWdOYW1lICYmIG5vZGUudGFnTmFtZSA9PT0gJ0EnICYmIG5vZGUuaHJlZikge1xuXHRcdFx0aWYgKG5vZGUuZ2V0QXR0cmlidXRlKCdocmVmJykuc3RhcnRzV2l0aCgnIycpKSB7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0aWYgKG5vZGUuaHJlZi5zdGFydHNXaXRoKCdmaWxlOi8vJykgfHwgbm9kZS5ocmVmLnN0YXJ0c1dpdGgoJ3ZzY29kZS1yZXNvdXJjZTonKSB8fCBub2RlLmhyZWYuc3RhcnRzV2l0aChzZXR0aW5ncy53ZWJ2aWV3UmVzb3VyY2VSb290KSkge1xuXHRcdFx0XHRjb25zdCBbcGF0aCwgZnJhZ21lbnRdID0gbm9kZS5ocmVmLnJlcGxhY2UoL14oZmlsZTpcXC9cXC98dnNjb2RlLXJlc291cmNlOikvaSwgJycpLnJlcGxhY2UobmV3IFJlZ0V4cChgXiR7ZXNjYXBlUmVnRXhwKHNldHRpbmdzLndlYnZpZXdSZXNvdXJjZVJvb3QpfWApKS5zcGxpdCgnIycpO1xuXHRcdFx0XHRtZXNzYWdpbmcucG9zdE1lc3NhZ2UoJ2NsaWNrTGluaycsIHsgcGF0aCwgZnJhZ21lbnQgfSk7XG5cdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGJyZWFrO1xuXHRcdH1cblx0XHRub2RlID0gbm9kZS5wYXJlbnROb2RlO1xuXHR9XG59LCB0cnVlKTtcblxuaWYgKHNldHRpbmdzLnNjcm9sbEVkaXRvcldpdGhQcmV2aWV3KSB7XG5cdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCB0aHJvdHRsZSgoKSA9PiB7XG5cdFx0aWYgKHNjcm9sbERpc2FibGVkKSB7XG5cdFx0XHRzY3JvbGxEaXNhYmxlZCA9IGZhbHNlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25zdCBsaW5lID0gZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQod2luZG93LnNjcm9sbFkpO1xuXHRcdFx0aWYgKHR5cGVvZiBsaW5lID09PSAnbnVtYmVyJyAmJiAhaXNOYU4obGluZSkpIHtcblx0XHRcdFx0bWVzc2FnaW5nLnBvc3RNZXNzYWdlKCdyZXZlYWxMaW5lJywgeyBsaW5lIH0pO1xuXHRcdFx0XHRzdGF0ZS5saW5lID0gbGluZTtcblx0XHRcdFx0dnNjb2RlLnNldFN0YXRlKHN0YXRlKTtcblx0XHRcdH1cblx0XHR9XG5cdH0sIDUwKSk7XG59XG5cbmZ1bmN0aW9uIGVzY2FwZVJlZ0V4cCh0ZXh0OiBzdHJpbmcpIHtcblx0cmV0dXJuIHRleHQucmVwbGFjZSgvWy1bXFxde30oKSorPy4sXFxcXF4kfCNcXHNdL2csICdcXFxcJCYnKTtcbn0iLCIvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuaW1wb3J0IHsgZ2V0U2V0dGluZ3MgfSBmcm9tICcuL3NldHRpbmdzJztcblxuZXhwb3J0IGludGVyZmFjZSBNZXNzYWdlUG9zdGVyIHtcblx0LyoqXG5cdCAqIFBvc3QgYSBtZXNzYWdlIHRvIHRoZSBtYXJrZG93biBleHRlbnNpb25cblx0ICovXG5cdHBvc3RNZXNzYWdlKHR5cGU6IHN0cmluZywgYm9keTogb2JqZWN0KTogdm9pZDtcbn1cblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVBvc3RlckZvclZzQ29kZSA9ICh2c2NvZGU6IGFueSkgPT4ge1xuXHRyZXR1cm4gbmV3IGNsYXNzIGltcGxlbWVudHMgTWVzc2FnZVBvc3RlciB7XG5cdFx0cG9zdE1lc3NhZ2UodHlwZTogc3RyaW5nLCBib2R5OiBvYmplY3QpOiB2b2lkIHtcblx0XHRcdHZzY29kZS5wb3N0TWVzc2FnZSh7XG5cdFx0XHRcdHR5cGUsXG5cdFx0XHRcdHNvdXJjZTogZ2V0U2V0dGluZ3MoKS5zb3VyY2UsXG5cdFx0XHRcdGJvZHlcblx0XHRcdH0pO1xuXHRcdH1cblx0fTtcbn07XG5cbiIsIi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5pbXBvcnQgeyBnZXRTZXR0aW5ncyB9IGZyb20gJy4vc2V0dGluZ3MnO1xuXG5cbmZ1bmN0aW9uIGNsYW1wKG1pbjogbnVtYmVyLCBtYXg6IG51bWJlciwgdmFsdWU6IG51bWJlcikge1xuXHRyZXR1cm4gTWF0aC5taW4obWF4LCBNYXRoLm1heChtaW4sIHZhbHVlKSk7XG59XG5cbmZ1bmN0aW9uIGNsYW1wTGluZShsaW5lOiBudW1iZXIpIHtcblx0cmV0dXJuIGNsYW1wKDAsIGdldFNldHRpbmdzKCkubGluZUNvdW50IC0gMSwgbGluZSk7XG59XG5cblxuZXhwb3J0IGludGVyZmFjZSBDb2RlTGluZUVsZW1lbnQge1xuXHRlbGVtZW50OiBIVE1MRWxlbWVudDtcblx0bGluZTogbnVtYmVyO1xufVxuXG5jb25zdCBnZXRDb2RlTGluZUVsZW1lbnRzID0gKCgpID0+IHtcblx0bGV0IGVsZW1lbnRzOiBDb2RlTGluZUVsZW1lbnRbXTtcblx0cmV0dXJuICgpID0+IHtcblx0XHRpZiAoIWVsZW1lbnRzKSB7XG5cdFx0XHRlbGVtZW50cyA9IFt7IGVsZW1lbnQ6IGRvY3VtZW50LmJvZHksIGxpbmU6IDAgfV07XG5cdFx0XHRmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnY29kZS1saW5lJykpIHtcblx0XHRcdFx0Y29uc3QgbGluZSA9ICtlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS1saW5lJykhO1xuXHRcdFx0XHRpZiAoIWlzTmFOKGxpbmUpKSB7XG5cdFx0XHRcdFx0ZWxlbWVudHMucHVzaCh7IGVsZW1lbnQ6IGVsZW1lbnQgYXMgSFRNTEVsZW1lbnQsIGxpbmUgfSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGVsZW1lbnRzO1xuXHR9O1xufSkoKTtcblxuLyoqXG4gKiBGaW5kIHRoZSBodG1sIGVsZW1lbnRzIHRoYXQgbWFwIHRvIGEgc3BlY2lmaWMgdGFyZ2V0IGxpbmUgaW4gdGhlIGVkaXRvci5cbiAqXG4gKiBJZiBhbiBleGFjdCBtYXRjaCwgcmV0dXJucyBhIHNpbmdsZSBlbGVtZW50LiBJZiB0aGUgbGluZSBpcyBiZXR3ZWVuIGVsZW1lbnRzLFxuICogcmV0dXJucyB0aGUgZWxlbWVudCBwcmlvciB0byBhbmQgdGhlIGVsZW1lbnQgYWZ0ZXIgdGhlIGdpdmVuIGxpbmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRFbGVtZW50c0ZvclNvdXJjZUxpbmUodGFyZ2V0TGluZTogbnVtYmVyKTogeyBwcmV2aW91czogQ29kZUxpbmVFbGVtZW50OyBuZXh0PzogQ29kZUxpbmVFbGVtZW50OyB9IHtcblx0Y29uc3QgbGluZU51bWJlciA9IE1hdGguZmxvb3IodGFyZ2V0TGluZSk7XG5cdGNvbnN0IGxpbmVzID0gZ2V0Q29kZUxpbmVFbGVtZW50cygpO1xuXHRsZXQgcHJldmlvdXMgPSBsaW5lc1swXSB8fCBudWxsO1xuXHRmb3IgKGNvbnN0IGVudHJ5IG9mIGxpbmVzKSB7XG5cdFx0aWYgKGVudHJ5LmxpbmUgPT09IGxpbmVOdW1iZXIpIHtcblx0XHRcdHJldHVybiB7IHByZXZpb3VzOiBlbnRyeSwgbmV4dDogdW5kZWZpbmVkIH07XG5cdFx0fSBlbHNlIGlmIChlbnRyeS5saW5lID4gbGluZU51bWJlcikge1xuXHRcdFx0cmV0dXJuIHsgcHJldmlvdXMsIG5leHQ6IGVudHJ5IH07XG5cdFx0fVxuXHRcdHByZXZpb3VzID0gZW50cnk7XG5cdH1cblx0cmV0dXJuIHsgcHJldmlvdXMgfTtcbn1cblxuLyoqXG4gKiBGaW5kIHRoZSBodG1sIGVsZW1lbnRzIHRoYXQgYXJlIGF0IGEgc3BlY2lmaWMgcGl4ZWwgb2Zmc2V0IG9uIHRoZSBwYWdlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0KG9mZnNldDogbnVtYmVyKTogeyBwcmV2aW91czogQ29kZUxpbmVFbGVtZW50OyBuZXh0PzogQ29kZUxpbmVFbGVtZW50OyB9IHtcblx0Y29uc3QgbGluZXMgPSBnZXRDb2RlTGluZUVsZW1lbnRzKCk7XG5cdGNvbnN0IHBvc2l0aW9uID0gb2Zmc2V0IC0gd2luZG93LnNjcm9sbFk7XG5cdGxldCBsbyA9IC0xO1xuXHRsZXQgaGkgPSBsaW5lcy5sZW5ndGggLSAxO1xuXHR3aGlsZSAobG8gKyAxIDwgaGkpIHtcblx0XHRjb25zdCBtaWQgPSBNYXRoLmZsb29yKChsbyArIGhpKSAvIDIpO1xuXHRcdGNvbnN0IGJvdW5kcyA9IGxpbmVzW21pZF0uZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0XHRpZiAoYm91bmRzLnRvcCArIGJvdW5kcy5oZWlnaHQgPj0gcG9zaXRpb24pIHtcblx0XHRcdGhpID0gbWlkO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGxvID0gbWlkO1xuXHRcdH1cblx0fVxuXHRjb25zdCBoaUVsZW1lbnQgPSBsaW5lc1toaV07XG5cdGNvbnN0IGhpQm91bmRzID0gaGlFbGVtZW50LmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cdGlmIChoaSA+PSAxICYmIGhpQm91bmRzLnRvcCA+IHBvc2l0aW9uKSB7XG5cdFx0Y29uc3QgbG9FbGVtZW50ID0gbGluZXNbbG9dO1xuXHRcdHJldHVybiB7IHByZXZpb3VzOiBsb0VsZW1lbnQsIG5leHQ6IGhpRWxlbWVudCB9O1xuXHR9XG5cdHJldHVybiB7IHByZXZpb3VzOiBoaUVsZW1lbnQgfTtcbn1cblxuLyoqXG4gKiBBdHRlbXB0IHRvIHJldmVhbCB0aGUgZWxlbWVudCBmb3IgYSBzb3VyY2UgbGluZSBpbiB0aGUgZWRpdG9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2Nyb2xsVG9SZXZlYWxTb3VyY2VMaW5lKGxpbmU6IG51bWJlcikge1xuXHRpZiAoIWdldFNldHRpbmdzKCkuc2Nyb2xsUHJldmlld1dpdGhFZGl0b3IpIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRpZiAobGluZSA8PSAwKSB7XG5cdFx0d2luZG93LnNjcm9sbCh3aW5kb3cuc2Nyb2xsWCwgMCk7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0Y29uc3QgeyBwcmV2aW91cywgbmV4dCB9ID0gZ2V0RWxlbWVudHNGb3JTb3VyY2VMaW5lKGxpbmUpO1xuXHRpZiAoIXByZXZpb3VzKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGxldCBzY3JvbGxUbyA9IDA7XG5cdGNvbnN0IHJlY3QgPSBwcmV2aW91cy5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXHRjb25zdCBwcmV2aW91c1RvcCA9IHJlY3QudG9wO1xuXHRpZiAobmV4dCAmJiBuZXh0LmxpbmUgIT09IHByZXZpb3VzLmxpbmUpIHtcblx0XHQvLyBCZXR3ZWVuIHR3byBlbGVtZW50cy4gR28gdG8gcGVyY2VudGFnZSBvZmZzZXQgYmV0d2VlbiB0aGVtLlxuXHRcdGNvbnN0IGJldHdlZW5Qcm9ncmVzcyA9IChsaW5lIC0gcHJldmlvdXMubGluZSkgLyAobmV4dC5saW5lIC0gcHJldmlvdXMubGluZSk7XG5cdFx0Y29uc3QgZWxlbWVudE9mZnNldCA9IG5leHQuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLSBwcmV2aW91c1RvcDtcblx0XHRzY3JvbGxUbyA9IHByZXZpb3VzVG9wICsgYmV0d2VlblByb2dyZXNzICogZWxlbWVudE9mZnNldDtcblx0fSBlbHNlIHtcblx0XHRjb25zdCBwcm9ncmVzc0luRWxlbWVudCA9IGxpbmUgLSBNYXRoLmZsb29yKGxpbmUpO1xuXHRcdHNjcm9sbFRvID0gcHJldmlvdXNUb3AgKyAocmVjdC5oZWlnaHQgKiBwcm9ncmVzc0luRWxlbWVudCk7XG5cdH1cblx0d2luZG93LnNjcm9sbCh3aW5kb3cuc2Nyb2xsWCwgTWF0aC5tYXgoMSwgd2luZG93LnNjcm9sbFkgKyBzY3JvbGxUbykpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RWRpdG9yTGluZU51bWJlckZvclBhZ2VPZmZzZXQob2Zmc2V0OiBudW1iZXIpIHtcblx0Y29uc3QgeyBwcmV2aW91cywgbmV4dCB9ID0gZ2V0TGluZUVsZW1lbnRzQXRQYWdlT2Zmc2V0KG9mZnNldCk7XG5cdGlmIChwcmV2aW91cykge1xuXHRcdGNvbnN0IHByZXZpb3VzQm91bmRzID0gcHJldmlvdXMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0XHRjb25zdCBvZmZzZXRGcm9tUHJldmlvdXMgPSAob2Zmc2V0IC0gd2luZG93LnNjcm9sbFkgLSBwcmV2aW91c0JvdW5kcy50b3ApO1xuXHRcdGlmIChuZXh0KSB7XG5cdFx0XHRjb25zdCBwcm9ncmVzc0JldHdlZW5FbGVtZW50cyA9IG9mZnNldEZyb21QcmV2aW91cyAvIChuZXh0LmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wIC0gcHJldmlvdXNCb3VuZHMudG9wKTtcblx0XHRcdGNvbnN0IGxpbmUgPSBwcmV2aW91cy5saW5lICsgcHJvZ3Jlc3NCZXR3ZWVuRWxlbWVudHMgKiAobmV4dC5saW5lIC0gcHJldmlvdXMubGluZSk7XG5cdFx0XHRyZXR1cm4gY2xhbXBMaW5lKGxpbmUpO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGNvbnN0IHByb2dyZXNzV2l0aGluRWxlbWVudCA9IG9mZnNldEZyb21QcmV2aW91cyAvIChwcmV2aW91c0JvdW5kcy5oZWlnaHQpO1xuXHRcdFx0Y29uc3QgbGluZSA9IHByZXZpb3VzLmxpbmUgKyBwcm9ncmVzc1dpdGhpbkVsZW1lbnQ7XG5cdFx0XHRyZXR1cm4gY2xhbXBMaW5lKGxpbmUpO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gbnVsbDtcbn1cbiIsIi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5leHBvcnQgaW50ZXJmYWNlIFByZXZpZXdTZXR0aW5ncyB7XG5cdHJlYWRvbmx5IHNvdXJjZTogc3RyaW5nO1xuXHRyZWFkb25seSBsaW5lOiBudW1iZXI7XG5cdHJlYWRvbmx5IGxpbmVDb3VudDogbnVtYmVyO1xuXHRyZWFkb25seSBzY3JvbGxQcmV2aWV3V2l0aEVkaXRvcj86IGJvb2xlYW47XG5cdHJlYWRvbmx5IHNjcm9sbEVkaXRvcldpdGhQcmV2aWV3OiBib29sZWFuO1xuXHRyZWFkb25seSBkaXNhYmxlU2VjdXJpdHlXYXJuaW5nczogYm9vbGVhbjtcblx0cmVhZG9ubHkgZG91YmxlQ2xpY2tUb1N3aXRjaFRvRWRpdG9yOiBib29sZWFuO1xuXHRyZWFkb25seSB3ZWJ2aWV3UmVzb3VyY2VSb290OiBzdHJpbmc7XG59XG5cbmxldCBjYWNoZWRTZXR0aW5nczogUHJldmlld1NldHRpbmdzIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGF0YTxUID0ge30+KGtleTogc3RyaW5nKTogVCB7XG5cdGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndnNjb2RlLW1hcmtkb3duLXByZXZpZXctZGF0YScpO1xuXHRpZiAoZWxlbWVudCkge1xuXHRcdGNvbnN0IGRhdGEgPSBlbGVtZW50LmdldEF0dHJpYnV0ZShrZXkpO1xuXHRcdGlmIChkYXRhKSB7XG5cdFx0XHRyZXR1cm4gSlNPTi5wYXJzZShkYXRhKTtcblx0XHR9XG5cdH1cblxuXHR0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBsb2FkIGRhdGEgZm9yICR7a2V5fWApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2V0dGluZ3MoKTogUHJldmlld1NldHRpbmdzIHtcblx0aWYgKGNhY2hlZFNldHRpbmdzKSB7XG5cdFx0cmV0dXJuIGNhY2hlZFNldHRpbmdzO1xuXHR9XG5cblx0Y2FjaGVkU2V0dGluZ3MgPSBnZXREYXRhKCdkYXRhLXNldHRpbmdzJyk7XG5cdGlmIChjYWNoZWRTZXR0aW5ncykge1xuXHRcdHJldHVybiBjYWNoZWRTZXR0aW5ncztcblx0fVxuXG5cdHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGxvYWQgc2V0dGluZ3MnKTtcbn1cbiJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/extensions/markdown-language-features/media/markdown.css b/extensions/markdown-language-features/media/markdown.css index 12145e43a66..273dc40f917 100644 --- a/extensions/markdown-language-features/media/markdown.css +++ b/extensions/markdown-language-features/media/markdown.css @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif; - font-size: 14px; +html, body { + font-family: var(--vscode-markdown-font-family, -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif); + font-size: var(--vscode-markdown-font-size, 14px); padding: 0 26px; - line-height: 22px; + line-height: var(--vscode-markdown-line-height, 22px); word-wrap: break-word; } @@ -32,7 +32,6 @@ body { box-shadow: 2px 2px 2px rgba(0,0,0,.25); } - body.scrollBeyondLastLine { margin-bottom: calc(100vh - 22px); } @@ -136,7 +135,6 @@ h3 code, h4 code, h5 code, h6 code { - font-size: inherit; line-height: auto; } @@ -169,19 +167,14 @@ blockquote { code { font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback"; - font-size: 14px; - line-height: 19px; + font-size: 1em; + line-height: 1.357em; } body.wordWrap pre { white-space: pre-wrap; } -.mac code { - font-size: 12px; - line-height: 18px; -} - pre:not(.hljs), pre.hljs code > div { padding: 16px; @@ -193,6 +186,7 @@ pre.hljs code > div { pre code { color: var(--vscode-editor-foreground); + tab-size: 4; } diff --git a/extensions/markdown-language-features/media/pre.js b/extensions/markdown-language-features/media/pre.js index bb0bd24f548..85e9c264915 100644 --- a/extensions/markdown-language-features/media/pre.js +++ b/extensions/markdown-language-features/media/pre.js @@ -277,4 +277,4 @@ exports.getStrings = getStrings; /***/ }) /******/ }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvY3NwLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2xvYWRpbmcudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvcHJlLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL3NldHRpbmdzLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL3N0cmluZ3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0EseURBQWlELGNBQWM7QUFDL0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQTJCLDBCQUEwQixFQUFFO0FBQ3ZELHlDQUFpQyxlQUFlO0FBQ2hEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhEQUFzRCwrREFBK0Q7O0FBRXJIO0FBQ0E7OztBQUdBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FDbkVBOzs7Z0dBR2dHOztBQUdoRyxzRkFBeUM7QUFDekMsbUZBQXVDO0FBRXZDOztHQUVHO0FBQ0g7SUFNQztRQUxRLFlBQU8sR0FBRyxLQUFLLENBQUM7UUFDaEIsc0JBQWlCLEdBQUcsS0FBSyxDQUFDO1FBS2pDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyx5QkFBeUIsRUFBRSxHQUFHLEVBQUU7WUFDekQsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3JCLENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQzVDLEVBQUUsQ0FBQyxDQUFDLEtBQUssSUFBSSxLQUFLLENBQUMsSUFBSSxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLHNCQUFzQixDQUFDLENBQUMsQ0FBQztnQkFDdkUsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3JCLENBQUM7UUFDRixDQUFDLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFTSxTQUFTLENBQUMsTUFBcUI7UUFDckMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUM7UUFDeEIsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztZQUM1QixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdkIsQ0FBQztJQUNGLENBQUM7SUFFTyxZQUFZO1FBQ25CLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7UUFDOUIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7SUFFTyxjQUFjO1FBQ3JCLE1BQU0sT0FBTyxHQUFHLG9CQUFVLEVBQUUsQ0FBQztRQUM3QixNQUFNLFFBQVEsR0FBRyxzQkFBVyxFQUFFLENBQUM7UUFFL0IsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sSUFBSSxRQUFRLENBQUMsdUJBQXVCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztZQUN6RSxNQUFNLENBQUM7UUFDUixDQUFDO1FBQ0QsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFFcEIsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNqRCxZQUFZLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQztRQUNyRCxZQUFZLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3BELFlBQVksQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBRWpFLFlBQVksQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzVDLFlBQVksQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ3RFLFlBQVksQ0FBQyxPQUFPLEdBQUcsR0FBRyxFQUFFO1lBQzNCLElBQUksQ0FBQyxTQUFVLENBQUMsV0FBVyxDQUFDLDZCQUE2QixFQUFFLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3pGLENBQUMsQ0FBQztRQUNGLFFBQVEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ3pDLENBQUM7Q0FDRDtBQW5ERCxnQ0FtREM7Ozs7Ozs7Ozs7Ozs7OztBQ3pERDtJQU1DO1FBTFEsbUJBQWMsR0FBYSxFQUFFLENBQUM7UUFDOUIsb0JBQWUsR0FBWSxLQUFLLENBQUM7UUFLeEMsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLEtBQVUsRUFBRSxFQUFFO1lBQ3ZDLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztZQUMzQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsQyxDQUFDLENBQUM7UUFFRixNQUFNLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxFQUFFO1lBQ2hELEdBQUcsQ0FBQyxDQUFDLE1BQU0sSUFBSSxJQUFJLFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQyxpQkFBaUIsQ0FBa0MsQ0FBQyxDQUFDLENBQUM7Z0JBQ3hHLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztvQkFDekIsSUFBSSxDQUFDLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQztnQkFDakMsQ0FBQztZQUNGLENBQUM7UUFDRixDQUFDLENBQUMsQ0FBQztRQUVILE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFO1lBQ3BDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUNqQyxNQUFNLENBQUM7WUFDUixDQUFDO1lBQ0QsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUM7WUFDNUIsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQ2pCLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLHVCQUF1QixFQUFFLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDO1lBQzNGLENBQUM7UUFDRixDQUFDLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFTSxTQUFTLENBQUMsTUFBcUI7UUFDckMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7WUFDMUIsTUFBTSxDQUFDLFdBQVcsQ0FBQyx1QkFBdUIsRUFBRSxFQUFFLGNBQWMsRUFBRSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztRQUN0RixDQUFDO0lBQ0YsQ0FBQztDQUNEO0FBckNELGtEQXFDQzs7Ozs7Ozs7Ozs7Ozs7QUMzQ0Q7OztnR0FHZ0c7O0FBRWhHLHVFQUFtQztBQUNuQyxtRkFBZ0Q7QUFTaEQsTUFBTSxDQUFDLFVBQVUsR0FBRyxJQUFJLGdCQUFVLEVBQUUsQ0FBQztBQUNyQyxNQUFNLENBQUMsbUJBQW1CLEdBQUcsSUFBSSw2QkFBbUIsRUFBRSxDQUFDOzs7Ozs7Ozs7Ozs7OztBQ2hCdkQ7OztnR0FHZ0c7O0FBWWhHLElBQUksY0FBYyxHQUFnQyxTQUFTLENBQUM7QUFFNUQsaUJBQXdCLEdBQVc7SUFDbEMsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO0lBQ3hFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDYixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDVixNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QixDQUFDO0lBQ0YsQ0FBQztJQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLEdBQUcsRUFBRSxDQUFDLENBQUM7QUFDbkQsQ0FBQztBQVZELDBCQVVDO0FBRUQ7SUFDQyxFQUFFLENBQUMsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxjQUFjLENBQUM7SUFDdkIsQ0FBQztJQUVELGNBQWMsR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDMUMsRUFBRSxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztRQUNwQixNQUFNLENBQUMsY0FBYyxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixDQUFDLENBQUM7QUFDNUMsQ0FBQztBQVhELGtDQVdDOzs7Ozs7Ozs7Ozs7OztBQ3hDRDs7O2dHQUdnRzs7QUFFaEc7SUFDQyxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDLDhCQUE4QixDQUFDLENBQUM7SUFDdEUsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNYLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDaEQsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNWLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pCLENBQUM7SUFDRixDQUFDO0lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0FBQzNDLENBQUM7QUFURCxnQ0FTQyIsImZpbGUiOiJwcmUuanMiLCJzb3VyY2VzQ29udGVudCI6WyIgXHQvLyBUaGUgbW9kdWxlIGNhY2hlXG4gXHR2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkge1xuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuIFx0XHR9XG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRpOiBtb2R1bGVJZCxcbiBcdFx0XHRsOiBmYWxzZSxcbiBcdFx0XHRleHBvcnRzOiB7fVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sID0gdHJ1ZTtcblxuIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gXHR9XG5cblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlIGNhY2hlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbiBcdFx0XHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbiBcdFx0XHR9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuIFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcblxuXG4gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbiBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IFwiLi9wcmV2aWV3LXNyYy9wcmUudHNcIik7XG4iLCIvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuaW1wb3J0IHsgTWVzc2FnZVBvc3RlciB9IGZyb20gJy4vbWVzc2FnaW5nJztcbmltcG9ydCB7IGdldFNldHRpbmdzIH0gZnJvbSAnLi9zZXR0aW5ncyc7XG5pbXBvcnQgeyBnZXRTdHJpbmdzIH0gZnJvbSAnLi9zdHJpbmdzJztcblxuLyoqXG4gKiBTaG93cyBhbiBhbGVydCB3aGVuIHRoZXJlIGlzIGEgY29udGVudCBzZWN1cml0eSBwb2xpY3kgdmlvbGF0aW9uLlxuICovXG5leHBvcnQgY2xhc3MgQ3NwQWxlcnRlciB7XG5cdHByaXZhdGUgZGlkU2hvdyA9IGZhbHNlO1xuXHRwcml2YXRlIGRpZEhhdmVDc3BXYXJuaW5nID0gZmFsc2U7XG5cblx0cHJpdmF0ZSBtZXNzYWdpbmc/OiBNZXNzYWdlUG9zdGVyO1xuXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3NlY3VyaXR5cG9saWN5dmlvbGF0aW9uJywgKCkgPT4ge1xuXHRcdFx0dGhpcy5vbkNzcFdhcm5pbmcoKTtcblx0XHR9KTtcblxuXHRcdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgKGV2ZW50KSA9PiB7XG5cdFx0XHRpZiAoZXZlbnQgJiYgZXZlbnQuZGF0YSAmJiBldmVudC5kYXRhLm5hbWUgPT09ICd2c2NvZGUtZGlkLWJsb2NrLXN2ZycpIHtcblx0XHRcdFx0dGhpcy5vbkNzcFdhcm5pbmcoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdHB1YmxpYyBzZXRQb3N0ZXIocG9zdGVyOiBNZXNzYWdlUG9zdGVyKSB7XG5cdFx0dGhpcy5tZXNzYWdpbmcgPSBwb3N0ZXI7XG5cdFx0aWYgKHRoaXMuZGlkSGF2ZUNzcFdhcm5pbmcpIHtcblx0XHRcdHRoaXMuc2hvd0NzcFdhcm5pbmcoKTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIG9uQ3NwV2FybmluZygpIHtcblx0XHR0aGlzLmRpZEhhdmVDc3BXYXJuaW5nID0gdHJ1ZTtcblx0XHR0aGlzLnNob3dDc3BXYXJuaW5nKCk7XG5cdH1cblxuXHRwcml2YXRlIHNob3dDc3BXYXJuaW5nKCkge1xuXHRcdGNvbnN0IHN0cmluZ3MgPSBnZXRTdHJpbmdzKCk7XG5cdFx0Y29uc3Qgc2V0dGluZ3MgPSBnZXRTZXR0aW5ncygpO1xuXG5cdFx0aWYgKHRoaXMuZGlkU2hvdyB8fCBzZXR0aW5ncy5kaXNhYmxlU2VjdXJpdHlXYXJuaW5ncyB8fCAhdGhpcy5tZXNzYWdpbmcpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy5kaWRTaG93ID0gdHJ1ZTtcblxuXHRcdGNvbnN0IG5vdGlmaWNhdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcblx0XHRub3RpZmljYXRpb24uaW5uZXJUZXh0ID0gc3RyaW5ncy5jc3BBbGVydE1lc3NhZ2VUZXh0O1xuXHRcdG5vdGlmaWNhdGlvbi5zZXRBdHRyaWJ1dGUoJ2lkJywgJ2NvZGUtY3NwLXdhcm5pbmcnKTtcblx0XHRub3RpZmljYXRpb24uc2V0QXR0cmlidXRlKCd0aXRsZScsIHN0cmluZ3MuY3NwQWxlcnRNZXNzYWdlVGl0bGUpO1xuXG5cdFx0bm90aWZpY2F0aW9uLnNldEF0dHJpYnV0ZSgncm9sZScsICdidXR0b24nKTtcblx0XHRub3RpZmljYXRpb24uc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgc3RyaW5ncy5jc3BBbGVydE1lc3NhZ2VMYWJlbCk7XG5cdFx0bm90aWZpY2F0aW9uLm9uY2xpY2sgPSAoKSA9PiB7XG5cdFx0XHR0aGlzLm1lc3NhZ2luZyEucG9zdE1lc3NhZ2UoJ3Nob3dQcmV2aWV3U2VjdXJpdHlTZWxlY3RvcicsIHsgc291cmNlOiBzZXR0aW5ncy5zb3VyY2UgfSk7XG5cdFx0fTtcblx0XHRkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKG5vdGlmaWNhdGlvbik7XG5cdH1cbn1cbiIsIi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuaW1wb3J0IHsgTWVzc2FnZVBvc3RlciB9IGZyb20gJy4vbWVzc2FnaW5nJztcblxuZXhwb3J0IGNsYXNzIFN0eWxlTG9hZGluZ01vbml0b3Ige1xuXHRwcml2YXRlIHVubG9hZGVkU3R5bGVzOiBzdHJpbmdbXSA9IFtdO1xuXHRwcml2YXRlIGZpbmlzaGVkTG9hZGluZzogYm9vbGVhbiA9IGZhbHNlO1xuXG5cdHByaXZhdGUgcG9zdGVyPzogTWVzc2FnZVBvc3RlcjtcblxuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRjb25zdCBvblN0eWxlTG9hZEVycm9yID0gKGV2ZW50OiBhbnkpID0+IHtcblx0XHRcdGNvbnN0IHNvdXJjZSA9IGV2ZW50LnRhcmdldC5kYXRhc2V0LnNvdXJjZTtcblx0XHRcdHRoaXMudW5sb2FkZWRTdHlsZXMucHVzaChzb3VyY2UpO1xuXHRcdH07XG5cblx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHtcblx0XHRcdGZvciAoY29uc3QgbGluayBvZiBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCdjb2RlLXVzZXItc3R5bGUnKSBhcyBIVE1MQ29sbGVjdGlvbk9mPEhUTUxFbGVtZW50Pikge1xuXHRcdFx0XHRpZiAobGluay5kYXRhc2V0LnNvdXJjZSkge1xuXHRcdFx0XHRcdGxpbmsub25lcnJvciA9IG9uU3R5bGVMb2FkRXJyb3I7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgKCkgPT4ge1xuXHRcdFx0aWYgKCF0aGlzLnVubG9hZGVkU3R5bGVzLmxlbmd0aCkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmZpbmlzaGVkTG9hZGluZyA9IHRydWU7XG5cdFx0XHRpZiAodGhpcy5wb3N0ZXIpIHtcblx0XHRcdFx0dGhpcy5wb3N0ZXIucG9zdE1lc3NhZ2UoJ3ByZXZpZXdTdHlsZUxvYWRFcnJvcicsIHsgdW5sb2FkZWRTdHlsZXM6IHRoaXMudW5sb2FkZWRTdHlsZXMgfSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHRwdWJsaWMgc2V0UG9zdGVyKHBvc3RlcjogTWVzc2FnZVBvc3Rlcik6IHZvaWQge1xuXHRcdHRoaXMucG9zdGVyID0gcG9zdGVyO1xuXHRcdGlmICh0aGlzLmZpbmlzaGVkTG9hZGluZykge1xuXHRcdFx0cG9zdGVyLnBvc3RNZXNzYWdlKCdwcmV2aWV3U3R5bGVMb2FkRXJyb3InLCB7IHVubG9hZGVkU3R5bGVzOiB0aGlzLnVubG9hZGVkU3R5bGVzIH0pO1xuXHRcdH1cblx0fVxufSIsIi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5pbXBvcnQgeyBDc3BBbGVydGVyIH0gZnJvbSAnLi9jc3AnO1xuaW1wb3J0IHsgU3R5bGVMb2FkaW5nTW9uaXRvciB9IGZyb20gJy4vbG9hZGluZyc7XG5cbmRlY2xhcmUgZ2xvYmFsIHtcblx0aW50ZXJmYWNlIFdpbmRvdyB7XG5cdFx0Y3NwQWxlcnRlcjogQ3NwQWxlcnRlcjtcblx0XHRzdHlsZUxvYWRpbmdNb25pdG9yOiBTdHlsZUxvYWRpbmdNb25pdG9yO1xuXHR9XG59XG5cbndpbmRvdy5jc3BBbGVydGVyID0gbmV3IENzcEFsZXJ0ZXIoKTtcbndpbmRvdy5zdHlsZUxvYWRpbmdNb25pdG9yID0gbmV3IFN0eWxlTG9hZGluZ01vbml0b3IoKTsiLCIvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuZXhwb3J0IGludGVyZmFjZSBQcmV2aWV3U2V0dGluZ3Mge1xuXHRzb3VyY2U6IHN0cmluZztcblx0bGluZTogbnVtYmVyO1xuXHRsaW5lQ291bnQ6IG51bWJlcjtcblx0c2Nyb2xsUHJldmlld1dpdGhFZGl0b3I/OiBib29sZWFuO1xuXHRzY3JvbGxFZGl0b3JXaXRoUHJldmlldzogYm9vbGVhbjtcblx0ZGlzYWJsZVNlY3VyaXR5V2FybmluZ3M6IGJvb2xlYW47XG5cdGRvdWJsZUNsaWNrVG9Td2l0Y2hUb0VkaXRvcjogYm9vbGVhbjtcbn1cblxubGV0IGNhY2hlZFNldHRpbmdzOiBQcmV2aWV3U2V0dGluZ3MgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREYXRhKGtleTogc3RyaW5nKTogUHJldmlld1NldHRpbmdzIHtcblx0Y29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2c2NvZGUtbWFya2Rvd24tcHJldmlldy1kYXRhJyk7XG5cdGlmIChlbGVtZW50KSB7XG5cdFx0Y29uc3QgZGF0YSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7XG5cdFx0aWYgKGRhdGEpIHtcblx0XHRcdHJldHVybiBKU09OLnBhcnNlKGRhdGEpO1xuXHRcdH1cblx0fVxuXG5cdHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGxvYWQgZGF0YSBmb3IgJHtrZXl9YCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTZXR0aW5ncygpOiBQcmV2aWV3U2V0dGluZ3Mge1xuXHRpZiAoY2FjaGVkU2V0dGluZ3MpIHtcblx0XHRyZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG5cdH1cblxuXHRjYWNoZWRTZXR0aW5ncyA9IGdldERhdGEoJ2RhdGEtc2V0dGluZ3MnKTtcblx0aWYgKGNhY2hlZFNldHRpbmdzKSB7XG5cdFx0cmV0dXJuIGNhY2hlZFNldHRpbmdzO1xuXHR9XG5cblx0dGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgbG9hZCBzZXR0aW5ncycpO1xufVxuIiwiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdHJpbmdzKCk6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0ge1xuXHRjb25zdCBzdG9yZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2c2NvZGUtbWFya2Rvd24tcHJldmlldy1kYXRhJyk7XG5cdGlmIChzdG9yZSkge1xuXHRcdGNvbnN0IGRhdGEgPSBzdG9yZS5nZXRBdHRyaWJ1dGUoJ2RhdGEtc3RyaW5ncycpO1xuXHRcdGlmIChkYXRhKSB7XG5cdFx0XHRyZXR1cm4gSlNPTi5wYXJzZShkYXRhKTtcblx0XHR9XG5cdH1cblx0dGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgbG9hZCBzdHJpbmdzJyk7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvY3NwLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL2xvYWRpbmcudHMiLCJ3ZWJwYWNrOi8vLy4vcHJldmlldy1zcmMvcHJlLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL3NldHRpbmdzLnRzIiwid2VicGFjazovLy8uL3ByZXZpZXctc3JjL3N0cmluZ3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0EseURBQWlELGNBQWM7QUFDL0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQTJCLDBCQUEwQixFQUFFO0FBQ3ZELHlDQUFpQyxlQUFlO0FBQ2hEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhEQUFzRCwrREFBK0Q7O0FBRXJIO0FBQ0E7OztBQUdBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FDbkVBOzs7Z0dBR2dHOztBQUdoRyxzRkFBeUM7QUFDekMsbUZBQXVDO0FBRXZDOztHQUVHO0FBQ0gsTUFBYSxVQUFVO0lBTXRCO1FBTFEsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUNoQixzQkFBaUIsR0FBRyxLQUFLLENBQUM7UUFLakMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLHlCQUF5QixFQUFFLEdBQUcsRUFBRTtZQUN6RCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDckIsQ0FBQyxDQUFDLENBQUM7UUFFSCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDNUMsSUFBSSxLQUFLLElBQUksS0FBSyxDQUFDLElBQUksSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxzQkFBc0IsRUFBRTtnQkFDdEUsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO2FBQ3BCO1FBQ0YsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0lBRU0sU0FBUyxDQUFDLE1BQXFCO1FBQ3JDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDO1FBQ3hCLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFO1lBQzNCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztTQUN0QjtJQUNGLENBQUM7SUFFTyxZQUFZO1FBQ25CLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7UUFDOUIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7SUFFTyxjQUFjO1FBQ3JCLE1BQU0sT0FBTyxHQUFHLG9CQUFVLEVBQUUsQ0FBQztRQUM3QixNQUFNLFFBQVEsR0FBRyxzQkFBVyxFQUFFLENBQUM7UUFFL0IsSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLFFBQVEsQ0FBQyx1QkFBdUIsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDeEUsT0FBTztTQUNQO1FBQ0QsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFFcEIsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNqRCxZQUFZLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQztRQUNyRCxZQUFZLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3BELFlBQVksQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBRWpFLFlBQVksQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzVDLFlBQVksQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ3RFLFlBQVksQ0FBQyxPQUFPLEdBQUcsR0FBRyxFQUFFO1lBQzNCLElBQUksQ0FBQyxTQUFVLENBQUMsV0FBVyxDQUFDLDZCQUE2QixFQUFFLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3pGLENBQUMsQ0FBQztRQUNGLFFBQVEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ3pDLENBQUM7Q0FDRDtBQW5ERCxnQ0FtREM7Ozs7Ozs7Ozs7Ozs7OztBQ3pERCxNQUFhLG1CQUFtQjtJQU0vQjtRQUxRLG1CQUFjLEdBQWEsRUFBRSxDQUFDO1FBQzlCLG9CQUFlLEdBQVksS0FBSyxDQUFDO1FBS3hDLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxLQUFVLEVBQUUsRUFBRTtZQUN2QyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7WUFDM0MsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbEMsQ0FBQyxDQUFDO1FBRUYsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGtCQUFrQixFQUFFLEdBQUcsRUFBRTtZQUNoRCxLQUFLLE1BQU0sSUFBSSxJQUFJLFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQyxpQkFBaUIsQ0FBa0MsRUFBRTtnQkFDdkcsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRTtvQkFDeEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQztpQkFDaEM7YUFDRDtRQUNGLENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUU7WUFDcEMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFO2dCQUNoQyxPQUFPO2FBQ1A7WUFDRCxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQztZQUM1QixJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7Z0JBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLHVCQUF1QixFQUFFLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDO2FBQzFGO1FBQ0YsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0lBRU0sU0FBUyxDQUFDLE1BQXFCO1FBQ3JDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRTtZQUN6QixNQUFNLENBQUMsV0FBVyxDQUFDLHVCQUF1QixFQUFFLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDO1NBQ3JGO0lBQ0YsQ0FBQztDQUNEO0FBckNELGtEQXFDQzs7Ozs7Ozs7Ozs7Ozs7QUMzQ0Q7OztnR0FHZ0c7O0FBRWhHLHVFQUFtQztBQUNuQyxtRkFBZ0Q7QUFTaEQsTUFBTSxDQUFDLFVBQVUsR0FBRyxJQUFJLGdCQUFVLEVBQUUsQ0FBQztBQUNyQyxNQUFNLENBQUMsbUJBQW1CLEdBQUcsSUFBSSw2QkFBbUIsRUFBRSxDQUFDOzs7Ozs7Ozs7Ozs7OztBQ2hCdkQ7OztnR0FHZ0c7O0FBYWhHLElBQUksY0FBYyxHQUFnQyxTQUFTLENBQUM7QUFFNUQsU0FBZ0IsT0FBTyxDQUFTLEdBQVc7SUFDMUMsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO0lBQ3hFLElBQUksT0FBTyxFQUFFO1FBQ1osTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QyxJQUFJLElBQUksRUFBRTtZQUNULE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUN4QjtLQUNEO0lBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQywyQkFBMkIsR0FBRyxFQUFFLENBQUMsQ0FBQztBQUNuRCxDQUFDO0FBVkQsMEJBVUM7QUFFRCxTQUFnQixXQUFXO0lBQzFCLElBQUksY0FBYyxFQUFFO1FBQ25CLE9BQU8sY0FBYyxDQUFDO0tBQ3RCO0lBRUQsY0FBYyxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUMxQyxJQUFJLGNBQWMsRUFBRTtRQUNuQixPQUFPLGNBQWMsQ0FBQztLQUN0QjtJQUVELE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztBQUM1QyxDQUFDO0FBWEQsa0NBV0M7Ozs7Ozs7Ozs7Ozs7O0FDekNEOzs7Z0dBR2dHOztBQUVoRyxTQUFnQixVQUFVO0lBQ3pCLE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsOEJBQThCLENBQUMsQ0FBQztJQUN0RSxJQUFJLEtBQUssRUFBRTtRQUNWLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDaEQsSUFBSSxJQUFJLEVBQUU7WUFDVCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDeEI7S0FDRDtJQUNELE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztBQUMzQyxDQUFDO0FBVEQsZ0NBU0MiLCJmaWxlIjoicHJlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbiBcdFx0XHRyZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcbiBcdFx0fVxuIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gXHRcdFx0aTogbW9kdWxlSWQsXG4gXHRcdFx0bDogZmFsc2UsXG4gXHRcdFx0ZXhwb3J0czoge31cbiBcdFx0fTtcblxuIFx0XHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cbiBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbiBcdFx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuIFx0XHRtb2R1bGUubCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gZGVmaW5lIGdldHRlciBmdW5jdGlvbiBmb3IgaGFybW9ueSBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiBcdFx0aWYoIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSkge1xuIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7XG4gXHRcdFx0XHRjb25maWd1cmFibGU6IGZhbHNlLFxuIFx0XHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcbiBcdFx0XHRcdGdldDogZ2V0dGVyXG4gXHRcdFx0fSk7XG4gXHRcdH1cbiBcdH07XG5cbiBcdC8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uciA9IGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiBcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbiBcdH07XG5cbiBcdC8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiBcdFx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHsgcmV0dXJuIG1vZHVsZVsnZGVmYXVsdCddOyB9IDpcbiBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCAnYScsIGdldHRlcik7XG4gXHRcdHJldHVybiBnZXR0ZXI7XG4gXHR9O1xuXG4gXHQvLyBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGxcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cblxuIFx0Ly8gTG9hZCBlbnRyeSBtb2R1bGUgYW5kIHJldHVybiBleHBvcnRzXG4gXHRyZXR1cm4gX193ZWJwYWNrX3JlcXVpcmVfXyhfX3dlYnBhY2tfcmVxdWlyZV9fLnMgPSBcIi4vcHJldmlldy1zcmMvcHJlLnRzXCIpO1xuIiwiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbmltcG9ydCB7IE1lc3NhZ2VQb3N0ZXIgfSBmcm9tICcuL21lc3NhZ2luZyc7XG5pbXBvcnQgeyBnZXRTZXR0aW5ncyB9IGZyb20gJy4vc2V0dGluZ3MnO1xuaW1wb3J0IHsgZ2V0U3RyaW5ncyB9IGZyb20gJy4vc3RyaW5ncyc7XG5cbi8qKlxuICogU2hvd3MgYW4gYWxlcnQgd2hlbiB0aGVyZSBpcyBhIGNvbnRlbnQgc2VjdXJpdHkgcG9saWN5IHZpb2xhdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIENzcEFsZXJ0ZXIge1xuXHRwcml2YXRlIGRpZFNob3cgPSBmYWxzZTtcblx0cHJpdmF0ZSBkaWRIYXZlQ3NwV2FybmluZyA9IGZhbHNlO1xuXG5cdHByaXZhdGUgbWVzc2FnaW5nPzogTWVzc2FnZVBvc3RlcjtcblxuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdzZWN1cml0eXBvbGljeXZpb2xhdGlvbicsICgpID0+IHtcblx0XHRcdHRoaXMub25Dc3BXYXJuaW5nKCk7XG5cdFx0fSk7XG5cblx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIChldmVudCkgPT4ge1xuXHRcdFx0aWYgKGV2ZW50ICYmIGV2ZW50LmRhdGEgJiYgZXZlbnQuZGF0YS5uYW1lID09PSAndnNjb2RlLWRpZC1ibG9jay1zdmcnKSB7XG5cdFx0XHRcdHRoaXMub25Dc3BXYXJuaW5nKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHRwdWJsaWMgc2V0UG9zdGVyKHBvc3RlcjogTWVzc2FnZVBvc3Rlcikge1xuXHRcdHRoaXMubWVzc2FnaW5nID0gcG9zdGVyO1xuXHRcdGlmICh0aGlzLmRpZEhhdmVDc3BXYXJuaW5nKSB7XG5cdFx0XHR0aGlzLnNob3dDc3BXYXJuaW5nKCk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBvbkNzcFdhcm5pbmcoKSB7XG5cdFx0dGhpcy5kaWRIYXZlQ3NwV2FybmluZyA9IHRydWU7XG5cdFx0dGhpcy5zaG93Q3NwV2FybmluZygpO1xuXHR9XG5cblx0cHJpdmF0ZSBzaG93Q3NwV2FybmluZygpIHtcblx0XHRjb25zdCBzdHJpbmdzID0gZ2V0U3RyaW5ncygpO1xuXHRcdGNvbnN0IHNldHRpbmdzID0gZ2V0U2V0dGluZ3MoKTtcblxuXHRcdGlmICh0aGlzLmRpZFNob3cgfHwgc2V0dGluZ3MuZGlzYWJsZVNlY3VyaXR5V2FybmluZ3MgfHwgIXRoaXMubWVzc2FnaW5nKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMuZGlkU2hvdyA9IHRydWU7XG5cblx0XHRjb25zdCBub3RpZmljYXRpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG5cdFx0bm90aWZpY2F0aW9uLmlubmVyVGV4dCA9IHN0cmluZ3MuY3NwQWxlcnRNZXNzYWdlVGV4dDtcblx0XHRub3RpZmljYXRpb24uc2V0QXR0cmlidXRlKCdpZCcsICdjb2RlLWNzcC13YXJuaW5nJyk7XG5cdFx0bm90aWZpY2F0aW9uLnNldEF0dHJpYnV0ZSgndGl0bGUnLCBzdHJpbmdzLmNzcEFsZXJ0TWVzc2FnZVRpdGxlKTtcblxuXHRcdG5vdGlmaWNhdGlvbi5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnYnV0dG9uJyk7XG5cdFx0bm90aWZpY2F0aW9uLnNldEF0dHJpYnV0ZSgnYXJpYS1sYWJlbCcsIHN0cmluZ3MuY3NwQWxlcnRNZXNzYWdlTGFiZWwpO1xuXHRcdG5vdGlmaWNhdGlvbi5vbmNsaWNrID0gKCkgPT4ge1xuXHRcdFx0dGhpcy5tZXNzYWdpbmchLnBvc3RNZXNzYWdlKCdzaG93UHJldmlld1NlY3VyaXR5U2VsZWN0b3InLCB7IHNvdXJjZTogc2V0dGluZ3Muc291cmNlIH0pO1xuXHRcdH07XG5cdFx0ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChub3RpZmljYXRpb24pO1xuXHR9XG59XG4iLCIvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmltcG9ydCB7IE1lc3NhZ2VQb3N0ZXIgfSBmcm9tICcuL21lc3NhZ2luZyc7XG5cbmV4cG9ydCBjbGFzcyBTdHlsZUxvYWRpbmdNb25pdG9yIHtcblx0cHJpdmF0ZSB1bmxvYWRlZFN0eWxlczogc3RyaW5nW10gPSBbXTtcblx0cHJpdmF0ZSBmaW5pc2hlZExvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuXHRwcml2YXRlIHBvc3Rlcj86IE1lc3NhZ2VQb3N0ZXI7XG5cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0Y29uc3Qgb25TdHlsZUxvYWRFcnJvciA9IChldmVudDogYW55KSA9PiB7XG5cdFx0XHRjb25zdCBzb3VyY2UgPSBldmVudC50YXJnZXQuZGF0YXNldC5zb3VyY2U7XG5cdFx0XHR0aGlzLnVubG9hZGVkU3R5bGVzLnB1c2goc291cmNlKTtcblx0XHR9O1xuXG5cdFx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCAoKSA9PiB7XG5cdFx0XHRmb3IgKGNvbnN0IGxpbmsgb2YgZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnY29kZS11c2VyLXN0eWxlJykgYXMgSFRNTENvbGxlY3Rpb25PZjxIVE1MRWxlbWVudD4pIHtcblx0XHRcdFx0aWYgKGxpbmsuZGF0YXNldC5zb3VyY2UpIHtcblx0XHRcdFx0XHRsaW5rLm9uZXJyb3IgPSBvblN0eWxlTG9hZEVycm9yO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsICgpID0+IHtcblx0XHRcdGlmICghdGhpcy51bmxvYWRlZFN0eWxlcy5sZW5ndGgpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5maW5pc2hlZExvYWRpbmcgPSB0cnVlO1xuXHRcdFx0aWYgKHRoaXMucG9zdGVyKSB7XG5cdFx0XHRcdHRoaXMucG9zdGVyLnBvc3RNZXNzYWdlKCdwcmV2aWV3U3R5bGVMb2FkRXJyb3InLCB7IHVubG9hZGVkU3R5bGVzOiB0aGlzLnVubG9hZGVkU3R5bGVzIH0pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0cHVibGljIHNldFBvc3Rlcihwb3N0ZXI6IE1lc3NhZ2VQb3N0ZXIpOiB2b2lkIHtcblx0XHR0aGlzLnBvc3RlciA9IHBvc3Rlcjtcblx0XHRpZiAodGhpcy5maW5pc2hlZExvYWRpbmcpIHtcblx0XHRcdHBvc3Rlci5wb3N0TWVzc2FnZSgncHJldmlld1N0eWxlTG9hZEVycm9yJywgeyB1bmxvYWRlZFN0eWxlczogdGhpcy51bmxvYWRlZFN0eWxlcyB9KTtcblx0XHR9XG5cdH1cbn0iLCIvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuaW1wb3J0IHsgQ3NwQWxlcnRlciB9IGZyb20gJy4vY3NwJztcbmltcG9ydCB7IFN0eWxlTG9hZGluZ01vbml0b3IgfSBmcm9tICcuL2xvYWRpbmcnO1xuXG5kZWNsYXJlIGdsb2JhbCB7XG5cdGludGVyZmFjZSBXaW5kb3cge1xuXHRcdGNzcEFsZXJ0ZXI6IENzcEFsZXJ0ZXI7XG5cdFx0c3R5bGVMb2FkaW5nTW9uaXRvcjogU3R5bGVMb2FkaW5nTW9uaXRvcjtcblx0fVxufVxuXG53aW5kb3cuY3NwQWxlcnRlciA9IG5ldyBDc3BBbGVydGVyKCk7XG53aW5kb3cuc3R5bGVMb2FkaW5nTW9uaXRvciA9IG5ldyBTdHlsZUxvYWRpbmdNb25pdG9yKCk7IiwiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJldmlld1NldHRpbmdzIHtcblx0cmVhZG9ubHkgc291cmNlOiBzdHJpbmc7XG5cdHJlYWRvbmx5IGxpbmU6IG51bWJlcjtcblx0cmVhZG9ubHkgbGluZUNvdW50OiBudW1iZXI7XG5cdHJlYWRvbmx5IHNjcm9sbFByZXZpZXdXaXRoRWRpdG9yPzogYm9vbGVhbjtcblx0cmVhZG9ubHkgc2Nyb2xsRWRpdG9yV2l0aFByZXZpZXc6IGJvb2xlYW47XG5cdHJlYWRvbmx5IGRpc2FibGVTZWN1cml0eVdhcm5pbmdzOiBib29sZWFuO1xuXHRyZWFkb25seSBkb3VibGVDbGlja1RvU3dpdGNoVG9FZGl0b3I6IGJvb2xlYW47XG5cdHJlYWRvbmx5IHdlYnZpZXdSZXNvdXJjZVJvb3Q6IHN0cmluZztcbn1cblxubGV0IGNhY2hlZFNldHRpbmdzOiBQcmV2aWV3U2V0dGluZ3MgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREYXRhPFQgPSB7fT4oa2V5OiBzdHJpbmcpOiBUIHtcblx0Y29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2c2NvZGUtbWFya2Rvd24tcHJldmlldy1kYXRhJyk7XG5cdGlmIChlbGVtZW50KSB7XG5cdFx0Y29uc3QgZGF0YSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7XG5cdFx0aWYgKGRhdGEpIHtcblx0XHRcdHJldHVybiBKU09OLnBhcnNlKGRhdGEpO1xuXHRcdH1cblx0fVxuXG5cdHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGxvYWQgZGF0YSBmb3IgJHtrZXl9YCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTZXR0aW5ncygpOiBQcmV2aWV3U2V0dGluZ3Mge1xuXHRpZiAoY2FjaGVkU2V0dGluZ3MpIHtcblx0XHRyZXR1cm4gY2FjaGVkU2V0dGluZ3M7XG5cdH1cblxuXHRjYWNoZWRTZXR0aW5ncyA9IGdldERhdGEoJ2RhdGEtc2V0dGluZ3MnKTtcblx0aWYgKGNhY2hlZFNldHRpbmdzKSB7XG5cdFx0cmV0dXJuIGNhY2hlZFNldHRpbmdzO1xuXHR9XG5cblx0dGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgbG9hZCBzZXR0aW5ncycpO1xufVxuIiwiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqICBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdHJpbmdzKCk6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0ge1xuXHRjb25zdCBzdG9yZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2c2NvZGUtbWFya2Rvd24tcHJldmlldy1kYXRhJyk7XG5cdGlmIChzdG9yZSkge1xuXHRcdGNvbnN0IGRhdGEgPSBzdG9yZS5nZXRBdHRyaWJ1dGUoJ2RhdGEtc3RyaW5ncycpO1xuXHRcdGlmIChkYXRhKSB7XG5cdFx0XHRyZXR1cm4gSlNPTi5wYXJzZShkYXRhKTtcblx0XHR9XG5cdH1cblx0dGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgbG9hZCBzdHJpbmdzJyk7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/extensions/markdown-language-features/media/preview-dark.svg b/extensions/markdown-language-features/media/preview-dark.svg new file mode 100644 index 00000000000..ec71ea81143 --- /dev/null +++ b/extensions/markdown-language-features/media/preview-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/markdown-language-features/media/preview-light.svg b/extensions/markdown-language-features/media/preview-light.svg new file mode 100644 index 00000000000..4a6b85b5839 --- /dev/null +++ b/extensions/markdown-language-features/media/preview-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/markdown-language-features/media/preview-right-dark.svg b/extensions/markdown-language-features/media/preview-right-dark.svg new file mode 100644 index 00000000000..1d59877196b --- /dev/null +++ b/extensions/markdown-language-features/media/preview-right-dark.svg @@ -0,0 +1,4 @@ + + + + diff --git a/extensions/markdown-language-features/media/preview-right-light.svg b/extensions/markdown-language-features/media/preview-right-light.svg new file mode 100644 index 00000000000..3f1152fc3cd --- /dev/null +++ b/extensions/markdown-language-features/media/preview-right-light.svg @@ -0,0 +1,4 @@ + + + + diff --git a/extensions/markdown-language-features/media/view-source-dark.svg b/extensions/markdown-language-features/media/view-source-dark.svg new file mode 100644 index 00000000000..ed302ae1398 --- /dev/null +++ b/extensions/markdown-language-features/media/view-source-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/markdown-language-features/media/view-source-light.svg b/extensions/markdown-language-features/media/view-source-light.svg new file mode 100644 index 00000000000..392a840c5ef --- /dev/null +++ b/extensions/markdown-language-features/media/view-source-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 8c65847f4df..0d74e1ac674 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -5,6 +5,8 @@ "version": "1.0.0", "icon": "icon.png", "publisher": "vscode", + "enableProposedApi": true, + "license": "MIT", "aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217", "engines": { "vscode": "^1.20.0" @@ -31,8 +33,8 @@ "title": "%markdown.preview.title%", "category": "Markdown", "icon": { - "light": "./media/Preview.svg", - "dark": "./media/Preview_inverse.svg" + "light": "./media/preview-light.svg", + "dark": "./media/preview-dark.svg" } }, { @@ -40,8 +42,8 @@ "title": "%markdown.previewSide.title%", "category": "Markdown", "icon": { - "light": "./media/PreviewOnRightPane_16x.svg", - "dark": "./media/PreviewOnRightPane_16x_dark.svg" + "light": "./media/preview-right-light.svg", + "dark": "./media/preview-right-dark.svg" } }, { @@ -49,8 +51,8 @@ "title": "%markdown.showLockedPreviewToSide.title%", "category": "Markdown", "icon": { - "light": "./media/PreviewOnRightPane_16x.svg", - "dark": "./media/PreviewOnRightPane_16x_dark.svg" + "light": "./media/preview-right-light.svg", + "dark": "./media/preview-right-dark.svg" } }, { @@ -58,8 +60,8 @@ "title": "%markdown.showSource.title%", "category": "Markdown", "icon": { - "light": "./media/ViewSource.svg", - "dark": "./media/ViewSource_inverse.svg" + "light": "./media/view-source-light.svg", + "dark": "./media/view-source-dark.svg" } }, { @@ -153,6 +155,14 @@ { "command": "markdown.preview.toggleLock", "when": "markdownPreviewFocus" + }, + { + "command": "markdown.preview.refresh", + "when": "editorLangId == markdown" + }, + { + "command": "markdown.preview.refresh", + "when": "markdownPreviewFocus" } ] }, @@ -177,20 +187,13 @@ "properties": { "markdown.styles": { "type": "array", + "items": { + "type": "string" + }, "default": [], "description": "%markdown.styles.dec%", "scope": "resource" }, - "markdown.previewFrontMatter": { - "type": "string", - "enum": [ - "hide", - "show" - ], - "default": "hide", - "description": "%markdown.previewFrontMatter.dec%", - "scope": "resource" - }, "markdown.preview.breaks": { "type": "boolean", "default": false, @@ -305,23 +308,24 @@ "build-preview": "webpack --mode development" }, "dependencies": { - "highlight.js": "9.13.1", + "highlight.js": "9.15.8", "markdown-it": "^8.4.2", - "vscode-extension-telemetry": "0.1.0", + "markdown-it-front-matter": "^0.1.2", + "vscode-extension-telemetry": "0.1.1", "vscode-nls": "^4.0.0" }, "devDependencies": { "@types/highlight.js": "9.12.3", "@types/lodash.throttle": "^4.1.3", "@types/markdown-it": "0.0.2", - "@types/node": "^8.10.25", + "@types/node": "^10.14.8", "lodash.throttle": "^4.1.1", "mocha-junit-reporter": "^1.17.0", "mocha-multi-reporters": "^1.1.7", "ts-loader": "^4.0.1", - "typescript": "^2.7.2", + "typescript": "^3.3.1", "vscode": "^1.1.10", "webpack": "^4.1.0", "webpack-cli": "^2.0.10" } -} +} \ No newline at end of file diff --git a/extensions/markdown-language-features/package.nls.json b/extensions/markdown-language-features/package.nls.json index ca3d7226f58..7841caff810 100644 --- a/extensions/markdown-language-features/package.nls.json +++ b/extensions/markdown-language-features/package.nls.json @@ -13,7 +13,6 @@ "markdown.preview.scrollPreviewWithEditorSelection.desc": "[Deprecated] Scrolls the markdown preview to reveal the currently selected line from the editor.", "markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "This setting has been replaced by 'markdown.preview.scrollPreviewWithEditor' and no longer has any effect.", "markdown.preview.title": "Open Preview", - "markdown.previewFrontMatter.dec": "Sets how YAML front matter should be rendered in the markdown preview. 'hide' removes the front matter. Otherwise, the front matter is treated as markdown content.", "markdown.previewSide.title": "Open Preview to the Side", "markdown.showLockedPreviewToSide.title": "Open Locked Preview to the Side", "markdown.showSource.title": "Show Source", diff --git a/extensions/markdown-language-features/preview-src/events.ts b/extensions/markdown-language-features/preview-src/events.ts index 40833aca711..81ce5c61640 100644 --- a/extensions/markdown-language-features/preview-src/events.ts +++ b/extensions/markdown-language-features/preview-src/events.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ export function onceDocumentLoaded(f: () => void) { - if (document.readyState === 'loading' || document.readyState === 'uninitialized') { + if (document.readyState === 'loading' || document.readyState as string === 'uninitialized') { document.addEventListener('DOMContentLoaded', f); } else { f(); diff --git a/extensions/markdown-language-features/preview-src/index.ts b/extensions/markdown-language-features/preview-src/index.ts index dff07def595..f78ae2f7972 100644 --- a/extensions/markdown-language-features/preview-src/index.ts +++ b/extensions/markdown-language-features/preview-src/index.ts @@ -19,7 +19,7 @@ const settings = getSettings(); const vscode = acquireVsCodeApi(); // Set VS Code state -const state = getData('data-state'); +let state = getData<{ line: number }>('data-state'); vscode.setState(state); const messaging = createPosterForVsCode(vscode); @@ -131,8 +131,8 @@ document.addEventListener('click', event => { if (node.getAttribute('href').startsWith('#')) { break; } - if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:')) { - const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-resource:)/i, '').split('#'); + if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:') || node.href.startsWith(settings.webviewResourceRoot)) { + const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-resource:)/i, '').replace(new RegExp(`^${escapeRegExp(settings.webviewResourceRoot)}`)).split('#'); messaging.postMessage('clickLink', { path, fragment }); event.preventDefault(); event.stopPropagation(); @@ -152,7 +152,13 @@ if (settings.scrollEditorWithPreview) { const line = getEditorLineNumberForPageOffset(window.scrollY); if (typeof line === 'number' && !isNaN(line)) { messaging.postMessage('revealLine', { line }); + state.line = line; + vscode.setState(state); } } }, 50)); +} + +function escapeRegExp(text: string) { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); } \ No newline at end of file diff --git a/extensions/markdown-language-features/preview-src/scroll-sync.ts b/extensions/markdown-language-features/preview-src/scroll-sync.ts index ce81b5ef092..4fe8987f6cd 100644 --- a/extensions/markdown-language-features/preview-src/scroll-sync.ts +++ b/extensions/markdown-language-features/preview-src/scroll-sync.ts @@ -24,13 +24,13 @@ const getCodeLineElements = (() => { let elements: CodeLineElement[]; return () => { if (!elements) { - elements = ([{ element: document.body, line: 0 }]).concat(Array.prototype.map.call( - document.getElementsByClassName('code-line'), - (element: any) => { - const line = +element.getAttribute('data-line'); - return { element, line }; - }) - .filter((x: any) => !isNaN(x.line))); + elements = [{ element: document.body, line: 0 }]; + for (const element of document.getElementsByClassName('code-line')) { + const line = +element.getAttribute('data-line')!; + if (!isNaN(line)) { + elements.push({ element: element as HTMLElement, line }); + } + } } return elements; }; diff --git a/extensions/markdown-language-features/preview-src/settings.ts b/extensions/markdown-language-features/preview-src/settings.ts index 46b03544c09..c77081b2659 100644 --- a/extensions/markdown-language-features/preview-src/settings.ts +++ b/extensions/markdown-language-features/preview-src/settings.ts @@ -4,18 +4,19 @@ *--------------------------------------------------------------------------------------------*/ export interface PreviewSettings { - source: string; - line: number; - lineCount: number; - scrollPreviewWithEditor?: boolean; - scrollEditorWithPreview: boolean; - disableSecurityWarnings: boolean; - doubleClickToSwitchToEditor: boolean; + readonly source: string; + readonly line: number; + readonly lineCount: number; + readonly scrollPreviewWithEditor?: boolean; + readonly scrollEditorWithPreview: boolean; + readonly disableSecurityWarnings: boolean; + readonly doubleClickToSwitchToEditor: boolean; + readonly webviewResourceRoot: string; } let cachedSettings: PreviewSettings | undefined = undefined; -export function getData(key: string): PreviewSettings { +export function getData(key: string): T { const element = document.getElementById('vscode-markdown-preview-data'); if (element) { const data = element.getAttribute(key); diff --git a/extensions/markdown-language-features/preview-src/tsconfig.json b/extensions/markdown-language-features/preview-src/tsconfig.json index 9684d1ec2d9..8a1e8a03fb8 100644 --- a/extensions/markdown-language-features/preview-src/tsconfig.json +++ b/extensions/markdown-language-features/preview-src/tsconfig.json @@ -6,6 +6,7 @@ "jsx": "react", "sourceMap": true, "strict": true, + "strictBindCallApply": true, "noImplicitAny": true, "noUnusedLocals": true } diff --git a/extensions/markdown-language-features/src/commands/openDocumentLink.ts b/extensions/markdown-language-features/src/commands/openDocumentLink.ts index 42dfe67df25..ea929f484f6 100644 --- a/extensions/markdown-language-features/src/commands/openDocumentLink.ts +++ b/extensions/markdown-language-features/src/commands/openDocumentLink.ts @@ -25,7 +25,7 @@ export class OpenDocumentLinkCommand implements Command { path: string, fragment: string ): vscode.Uri { - return vscode.Uri.parse(`command:${OpenDocumentLinkCommand.id}?${encodeURIComponent(JSON.stringify({ path, fragment }))}`); + return vscode.Uri.parse(`command:${OpenDocumentLinkCommand.id}?${encodeURIComponent(JSON.stringify({ path: encodeURIComponent(path), fragment }))}`); } public constructor( diff --git a/extensions/markdown-language-features/src/commands/refreshPreview.ts b/extensions/markdown-language-features/src/commands/refreshPreview.ts index fb1bb829960..6fbeed98191 100644 --- a/extensions/markdown-language-features/src/commands/refreshPreview.ts +++ b/extensions/markdown-language-features/src/commands/refreshPreview.ts @@ -5,15 +5,18 @@ import { Command } from '../commandManager'; import { MarkdownPreviewManager } from '../features/previewManager'; +import { MarkdownEngine } from '../markdownEngine'; export class RefreshPreviewCommand implements Command { public readonly id = 'markdown.preview.refresh'; public constructor( - private readonly webviewManager: MarkdownPreviewManager + private readonly webviewManager: MarkdownPreviewManager, + private readonly engine: MarkdownEngine ) { } public execute() { + this.engine.cleanCache(); this.webviewManager.refresh(); } } \ No newline at end of file diff --git a/extensions/markdown-language-features/src/commands/showPreviewSecuritySelector.ts b/extensions/markdown-language-features/src/commands/showPreviewSecuritySelector.ts index 2e520415ebc..4e3ea87d4c5 100644 --- a/extensions/markdown-language-features/src/commands/showPreviewSecuritySelector.ts +++ b/extensions/markdown-language-features/src/commands/showPreviewSecuritySelector.ts @@ -19,12 +19,12 @@ export class ShowPreviewSecuritySelectorCommand implements Command { public execute(resource: string | undefined) { if (this.previewManager.activePreviewResource) { - this.previewSecuritySelector.showSecutitySelectorForResource(this.previewManager.activePreviewResource); + this.previewSecuritySelector.showSecuritySelectorForResource(this.previewManager.activePreviewResource); } else if (resource) { const source = vscode.Uri.parse(resource); - this.previewSecuritySelector.showSecutitySelectorForResource(source.query ? vscode.Uri.parse(source.query) : source); + this.previewSecuritySelector.showSecuritySelectorForResource(source.query ? vscode.Uri.parse(source.query) : source); } else if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document)) { - this.previewSecuritySelector.showSecutitySelectorForResource(vscode.window.activeTextEditor.document.uri); + this.previewSecuritySelector.showSecuritySelectorForResource(vscode.window.activeTextEditor.document.uri); } } } \ No newline at end of file diff --git a/extensions/markdown-language-features/src/commands/showSource.ts b/extensions/markdown-language-features/src/commands/showSource.ts index a916bccefc0..d61a3211e8c 100644 --- a/extensions/markdown-language-features/src/commands/showSource.ts +++ b/extensions/markdown-language-features/src/commands/showSource.ts @@ -15,9 +15,11 @@ export class ShowSourceCommand implements Command { ) { } public execute() { - if (this.previewManager.activePreviewResource) { - return vscode.workspace.openTextDocument(this.previewManager.activePreviewResource) - .then(document => vscode.window.showTextDocument(document)); + const { activePreviewResource, activePreviewResourceColumn } = this.previewManager; + if (activePreviewResource && activePreviewResourceColumn) { + return vscode.workspace.openTextDocument(activePreviewResource).then(document => { + vscode.window.showTextDocument(document, activePreviewResourceColumn); + }); } return undefined; } diff --git a/extensions/markdown-language-features/src/extension.ts b/extensions/markdown-language-features/src/extension.ts index a90a0124843..3fe2c9d4cd3 100644 --- a/extensions/markdown-language-features/src/extension.ts +++ b/extensions/markdown-language-features/src/extension.ts @@ -15,8 +15,8 @@ import MarkdownWorkspaceSymbolProvider from './features/workspaceSymbolProvider' import { Logger } from './logger'; import { MarkdownEngine } from './markdownEngine'; import { getMarkdownExtensionContributions } from './markdownExtensions'; -import { ExtensionContentSecurityPolicyArbiter, PreviewSecuritySelector } from './security'; -import { loadDefaultTelemetryReporter } from './telemetryReporter'; +import { ExtensionContentSecurityPolicyArbiter, PreviewSecuritySelector, ContentSecurityPolicyArbiter } from './security'; +import { loadDefaultTelemetryReporter, TelemetryReporter } from './telemetryReporter'; import { githubSlugifier } from './slugify'; @@ -25,45 +25,64 @@ export function activate(context: vscode.ExtensionContext) { context.subscriptions.push(telemetryReporter); const contributions = getMarkdownExtensionContributions(context); + context.subscriptions.push(contributions); const cspArbiter = new ExtensionContentSecurityPolicyArbiter(context.globalState, context.workspaceState); const engine = new MarkdownEngine(contributions, githubSlugifier); const logger = new Logger(); - const selector: vscode.DocumentSelector = [ - { language: 'markdown', scheme: 'file' }, - { language: 'markdown', scheme: 'untitled' } - ]; - const contentProvider = new MarkdownContentProvider(engine, context, cspArbiter, contributions, logger); const symbolProvider = new MDDocumentSymbolProvider(engine); const previewManager = new MarkdownPreviewManager(contentProvider, logger, contributions); context.subscriptions.push(previewManager); - context.subscriptions.push(vscode.languages.setLanguageConfiguration('markdown', { - wordPattern: new RegExp('(\\p{Alphabetic}|\\p{Number})+', 'ug'), - })); - context.subscriptions.push(vscode.languages.registerDocumentSymbolProvider(selector, symbolProvider)); - context.subscriptions.push(vscode.languages.registerDocumentLinkProvider(selector, new LinkProvider())); - context.subscriptions.push(vscode.languages.registerFoldingRangeProvider(selector, new MarkdownFoldingProvider(engine))); - context.subscriptions.push(vscode.languages.registerWorkspaceSymbolProvider(new MarkdownWorkspaceSymbolProvider(symbolProvider))); - - const previewSecuritySelector = new PreviewSecuritySelector(cspArbiter, previewManager); - - const commandManager = new CommandManager(); - context.subscriptions.push(commandManager); - commandManager.register(new commands.ShowPreviewCommand(previewManager, telemetryReporter)); - commandManager.register(new commands.ShowPreviewToSideCommand(previewManager, telemetryReporter)); - commandManager.register(new commands.ShowLockedPreviewToSideCommand(previewManager, telemetryReporter)); - commandManager.register(new commands.ShowSourceCommand(previewManager)); - commandManager.register(new commands.RefreshPreviewCommand(previewManager)); - commandManager.register(new commands.MoveCursorToPositionCommand()); - commandManager.register(new commands.ShowPreviewSecuritySelectorCommand(previewSecuritySelector, previewManager)); - commandManager.register(new commands.OpenDocumentLinkCommand(engine)); - commandManager.register(new commands.ToggleLockCommand(previewManager)); + context.subscriptions.push(registerMarkdownLanguageFeatures(symbolProvider, engine)); + context.subscriptions.push(registerMarkdownCommands(previewManager, telemetryReporter, cspArbiter, engine)); context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(() => { logger.updateConfiguration(); previewManager.updateConfiguration(); })); } + +function registerMarkdownLanguageFeatures( + symbolProvider: MDDocumentSymbolProvider, + engine: MarkdownEngine +): vscode.Disposable { + const selector: vscode.DocumentSelector = [ + { language: 'markdown', scheme: 'file' }, + { language: 'markdown', scheme: 'untitled' } + ]; + + return vscode.Disposable.from( + vscode.languages.setLanguageConfiguration('markdown', { + wordPattern: new RegExp('(\\p{Alphabetic}|\\p{Number})+', 'ug'), + }), + vscode.languages.registerDocumentSymbolProvider(selector, symbolProvider), + vscode.languages.registerDocumentLinkProvider(selector, new LinkProvider()), + vscode.languages.registerFoldingRangeProvider(selector, new MarkdownFoldingProvider(engine)), + vscode.languages.registerWorkspaceSymbolProvider(new MarkdownWorkspaceSymbolProvider(symbolProvider)) + ); +} + +function registerMarkdownCommands( + previewManager: MarkdownPreviewManager, + telemetryReporter: TelemetryReporter, + cspArbiter: ContentSecurityPolicyArbiter, + engine: MarkdownEngine +): vscode.Disposable { + const previewSecuritySelector = new PreviewSecuritySelector(cspArbiter, previewManager); + + const commandManager = new CommandManager(); + commandManager.register(new commands.ShowPreviewCommand(previewManager, telemetryReporter)); + commandManager.register(new commands.ShowPreviewToSideCommand(previewManager, telemetryReporter)); + commandManager.register(new commands.ShowLockedPreviewToSideCommand(previewManager, telemetryReporter)); + commandManager.register(new commands.ShowSourceCommand(previewManager)); + commandManager.register(new commands.RefreshPreviewCommand(previewManager, engine)); + commandManager.register(new commands.MoveCursorToPositionCommand()); + commandManager.register(new commands.ShowPreviewSecuritySelectorCommand(previewSecuritySelector, previewManager)); + commandManager.register(new commands.OpenDocumentLinkCommand(engine)); + commandManager.register(new commands.ToggleLockCommand(previewManager)); + return commandManager; +} + diff --git a/extensions/markdown-language-features/src/features/documentLinkProvider.ts b/extensions/markdown-language-features/src/features/documentLinkProvider.ts index f4e1bd0a9d2..c4344a632bd 100644 --- a/extensions/markdown-language-features/src/features/documentLinkProvider.ts +++ b/extensions/markdown-language-features/src/features/documentLinkProvider.ts @@ -5,17 +5,20 @@ import * as path from 'path'; import * as vscode from 'vscode'; +import * as nls from 'vscode-nls'; import { OpenDocumentLinkCommand } from '../commands/openDocumentLink'; import { getUriForLinkWithKnownExternalScheme } from '../util/links'; -function normalizeLink( +const localize = nls.loadMessageBundle(); + +function parseLink( document: vscode.TextDocument, link: string, base: string -): vscode.Uri { +): { uri: vscode.Uri, tooltip?: string } { const externalSchemeUri = getUriForLinkWithKnownExternalScheme(link); if (externalSchemeUri) { - return externalSchemeUri; + return { uri: externalSchemeUri }; } // Assume it must be an relative or absolute file path @@ -34,7 +37,10 @@ function normalizeLink( resourcePath = base ? path.join(base, tempUri.path) : tempUri.path; } - return OpenDocumentLinkCommand.createCommandUri(resourcePath, tempUri.fragment); + return { + uri: OpenDocumentLinkCommand.createCommandUri(resourcePath, tempUri.fragment), + tooltip: localize('documentLink.tooltip', 'Follow link') + }; } function matchAll( @@ -50,10 +56,32 @@ function matchAll( return out; } +function extractDocumentLink( + document: vscode.TextDocument, + base: string, + pre: number, + link: string, + matchIndex: number | undefined +): vscode.DocumentLink | undefined { + const offset = (matchIndex || 0) + pre; + const linkStart = document.positionAt(offset); + const linkEnd = document.positionAt(offset + link.length); + try { + const { uri, tooltip } = parseLink(document, link, base); + const documentLink = new vscode.DocumentLink( + new vscode.Range(linkStart, linkEnd), + uri); + documentLink.tooltip = tooltip; + return documentLink; + } catch (e) { + return undefined; + } +} + export default class LinkProvider implements vscode.DocumentLinkProvider { - private readonly linkPattern = /(\[[^\]]*\]\(\s*)((([^\s\(\)]|\(\S*?\))+))\s*(".*?")?\)/g; - private readonly referenceLinkPattern = /(\[([^\]]+)\]\[\s*?)([^\s\]]*?)\]/g; - private readonly definitionPattern = /^([\t ]*\[([^\]]+)\]:\s*)(\S+)/gm; + private readonly linkPattern = /(\[((!\[[^\]]*?\]\(\s*)([^\s\(\)]+?)\s*\)\]|(?:\\\]|[^\]])*\])\(\s*)(([^\s\(\)]|\(\S*?\))+)\s*(".*?")?\)/g; + private readonly referenceLinkPattern = /(\[((?:\\\]|[^\]])+)\]\[\s*?)([^\s\]]*?)\]/g; + private readonly definitionPattern = /^([\t ]*\[((?:\\\]|[^\]])+)\]:\s*)(\S+)/gm; public provideDocumentLinks( document: vscode.TextDocument, @@ -62,8 +90,10 @@ export default class LinkProvider implements vscode.DocumentLinkProvider { const base = document.uri.scheme === 'file' ? path.dirname(document.uri.fsPath) : ''; const text = document.getText(); - return this.providerInlineLinks(text, document, base) - .concat(this.provideReferenceLinks(text, document, base)); + return [ + ...this.providerInlineLinks(text, document, base), + ...this.provideReferenceLinks(text, document, base) + ]; } private providerInlineLinks( @@ -73,20 +103,15 @@ export default class LinkProvider implements vscode.DocumentLinkProvider { ): vscode.DocumentLink[] { const results: vscode.DocumentLink[] = []; for (const match of matchAll(this.linkPattern, text)) { - const pre = match[1]; - const link = match[2]; - const offset = (match.index || 0) + pre.length; - const linkStart = document.positionAt(offset); - const linkEnd = document.positionAt(offset + link.length); - try { - results.push(new vscode.DocumentLink( - new vscode.Range(linkStart, linkEnd), - normalizeLink(document, link, base))); - } catch (e) { - // noop + const matchImage = match[4] && extractDocumentLink(document, base, match[3].length + 1, match[4], match.index); + if (matchImage) { + results.push(matchImage); + } + const matchLink = extractDocumentLink(document, base, match[1].length, match[5], match.index); + if (matchLink) { + results.push(matchLink); } } - return results; } @@ -128,11 +153,10 @@ export default class LinkProvider implements vscode.DocumentLinkProvider { } } - for (const definition of Array.from(definitions.values())) { + for (const definition of definitions.values()) { try { - results.push(new vscode.DocumentLink( - definition.linkRange, - normalizeLink(document, definition.link, base))); + const { uri } = parseLink(document, definition.link, base); + results.push(new vscode.DocumentLink(definition.linkRange, uri)); } catch (e) { // noop } @@ -159,4 +183,4 @@ export default class LinkProvider implements vscode.DocumentLinkProvider { } return out; } -} +} \ No newline at end of file diff --git a/extensions/markdown-language-features/src/features/foldingProvider.ts b/extensions/markdown-language-features/src/features/foldingProvider.ts index 9e98cfd67b3..4850b3759de 100644 --- a/extensions/markdown-language-features/src/features/foldingProvider.ts +++ b/extensions/markdown-language-features/src/features/foldingProvider.ts @@ -7,24 +7,36 @@ import { Token } from 'markdown-it'; import * as vscode from 'vscode'; import { MarkdownEngine } from '../markdownEngine'; import { TableOfContentsProvider } from '../tableOfContentsProvider'; +import { flatten } from '../util/arrays'; const rangeLimit = 5000; +const isStartRegion = (t: string) => /^\s*/.test(t); +const isEndRegion = (t: string) => /^\s*/.test(t); + +const isRegionMarker = (token: Token) => + token.type === 'html_block' && (isStartRegion(token.content) || isEndRegion(token.content)); + export default class MarkdownFoldingProvider implements vscode.FoldingRangeProvider { constructor( private readonly engine: MarkdownEngine ) { } + public async provideFoldingRanges( + document: vscode.TextDocument, + _: vscode.FoldingContext, + _token: vscode.CancellationToken + ): Promise { + const foldables = await Promise.all([ + this.getRegions(document), + this.getHeaderFoldingRanges(document), + this.getBlockFoldingRanges(document) + ]); + return flatten(foldables).slice(0, rangeLimit); + } + private async getRegions(document: vscode.TextDocument): Promise { - - const isStartRegion = (t: string) => /^\s*/.test(t); - const isEndRegion = (t: string) => /^\s*/.test(t); - - const isRegionMarker = (token: Token) => token.type === 'html_block' && - (isStartRegion(token.content) || isEndRegion(token.content)); - - const tokens = await this.engine.parse(document); const regionMarkers = tokens.filter(isRegionMarker) .map(token => ({ line: token.map[0], isStart: isStartRegion(token.content) })); @@ -44,18 +56,6 @@ export default class MarkdownFoldingProvider implements vscode.FoldingRangeProvi .filter((region: vscode.FoldingRange | null): region is vscode.FoldingRange => !!region); } - public async provideFoldingRanges( - document: vscode.TextDocument, - _: vscode.FoldingContext, - _token: vscode.CancellationToken - ): Promise { - const foldables = await Promise.all([ - this.getRegions(document), - this.getHeaderFoldingRanges(document), - this.getBlockFoldingRanges(document)]); - return ([] as vscode.FoldingRange[]).concat.apply([], foldables).slice(0, rangeLimit); - } - private async getHeaderFoldingRanges(document: vscode.TextDocument) { const tocProvider = new TableOfContentsProvider(this.engine, document); const toc = await tocProvider.getToc(); @@ -70,7 +70,7 @@ export default class MarkdownFoldingProvider implements vscode.FoldingRangeProvi private async getBlockFoldingRanges(document: vscode.TextDocument): Promise { - const isFoldableToken = (token: Token) => { + const isFoldableToken = (token: Token): boolean => { switch (token.type) { case 'fence': case 'list_item_open': diff --git a/extensions/markdown-language-features/src/features/preview.ts b/extensions/markdown-language-features/src/features/preview.ts index c82cee6c7d7..c874f5791ed 100644 --- a/extensions/markdown-language-features/src/features/preview.ts +++ b/extensions/markdown-language-features/src/features/preview.ts @@ -8,14 +8,15 @@ import * as path from 'path'; import { Logger } from '../logger'; import { MarkdownContentProvider } from './previewContentProvider'; -import { disposeAll } from '../util/dispose'; +import { Disposable } from '../util/dispose'; import * as nls from 'vscode-nls'; import { getVisibleLine, MarkdownFileTopmostLineMonitor } from '../util/topmostLineMonitor'; import { MarkdownPreviewConfigurationManager } from './previewConfig'; -import { MarkdownContributions } from '../markdownExtensions'; +import { MarkdownContributionProvider, MarkdownContributions } from '../markdownExtensions'; import { isMarkdownFile } from '../util/file'; import { resolveLinkToMarkdownFile } from '../commands/openDocumentLink'; +import { WebviewResourceProvider, normalizeResource } from '../util/resources'; const localize = nls.loadMessageBundle(); interface WebviewMessage { @@ -60,9 +61,21 @@ interface PreviewStyleLoadErrorMessage extends WebviewMessage { }; } -export class MarkdownPreview { +export class PreviewDocumentVersion { + public constructor( + public readonly resource: vscode.Uri, + public readonly version: number, + ) { } - public static viewType = 'markdown.preview'; + public equals(other: PreviewDocumentVersion): boolean { + return this.resource.fsPath === other.resource.fsPath + && this.version === other.version; + } +} + +export class MarkdownPreview extends Disposable { + + public static readonly viewType = 'markdown.preview'; private _resource: vscode.Uri; private _locked: boolean; @@ -70,9 +83,8 @@ export class MarkdownPreview { private readonly editor: vscode.WebviewPanel; private throttleTimer: any; private line: number | undefined = undefined; - private readonly disposables: vscode.Disposable[] = []; private firstUpdate = true; - private currentVersion?: { resource: vscode.Uri, version: number }; + private currentVersion?: PreviewDocumentVersion; private forceUpdate = false; private isScrolling = false; private _disposed: boolean = false; @@ -85,23 +97,25 @@ export class MarkdownPreview { previewConfigurations: MarkdownPreviewConfigurationManager, logger: Logger, topmostLineMonitor: MarkdownFileTopmostLineMonitor, - contributions: MarkdownContributions, + contributionProvider: MarkdownContributionProvider, ): Promise { const resource = vscode.Uri.parse(state.resource); const locked = state.locked; const line = state.line; + const resourceColumn = state.resourceColumn; const preview = new MarkdownPreview( webview, resource, locked, + resourceColumn, contentProvider, previewConfigurations, logger, topmostLineMonitor, - contributions); + contributionProvider); - preview.editor.webview.options = MarkdownPreview.getWebviewOptions(resource, contributions); + preview.editor.webview.options = MarkdownPreview.getWebviewOptions(resource, contributionProvider.contributions); if (!isNaN(line)) { preview.line = line; @@ -113,53 +127,61 @@ export class MarkdownPreview { public static create( resource: vscode.Uri, previewColumn: vscode.ViewColumn, + resourceColumn: vscode.ViewColumn, locked: boolean, contentProvider: MarkdownContentProvider, previewConfigurations: MarkdownPreviewConfigurationManager, logger: Logger, topmostLineMonitor: MarkdownFileTopmostLineMonitor, - contributions: MarkdownContributions + contributionProvider: MarkdownContributionProvider ): MarkdownPreview { const webview = vscode.window.createWebviewPanel( MarkdownPreview.viewType, MarkdownPreview.getPreviewTitle(resource, locked), previewColumn, { enableFindWidget: true, - ...MarkdownPreview.getWebviewOptions(resource, contributions) + ...MarkdownPreview.getWebviewOptions(resource, contributionProvider.contributions) }); return new MarkdownPreview( webview, resource, locked, + resourceColumn, contentProvider, previewConfigurations, logger, topmostLineMonitor, - contributions); + contributionProvider); } private constructor( webview: vscode.WebviewPanel, resource: vscode.Uri, locked: boolean, + private readonly _resourceColumn: vscode.ViewColumn, private readonly _contentProvider: MarkdownContentProvider, private readonly _previewConfigurations: MarkdownPreviewConfigurationManager, private readonly _logger: Logger, topmostLineMonitor: MarkdownFileTopmostLineMonitor, - private readonly _contributions: MarkdownContributions, + private readonly _contributionProvider: MarkdownContributionProvider, ) { + super(); this._resource = resource; this._locked = locked; this.editor = webview; this.editor.onDidDispose(() => { this.dispose(); - }, null, this.disposables); + }, null, this._disposables); this.editor.onDidChangeViewState(e => { this._onDidChangeViewStateEmitter.fire(e); - }, null, this.disposables); + }, null, this._disposables); + + _contributionProvider.onContributionsChanged(() => { + setImmediate(() => this.refresh()); + }, null, this._disposables); this.editor.webview.onDidReceiveMessage((e: CacheImageSizesMessage | RevealLineMessage | DidClickMessage | ClickLinkMessage | ShowPreviewSecuritySelectorMessage | PreviewStyleLoadErrorMessage) => { if (e.source !== this._resource.toString()) { @@ -191,19 +213,19 @@ export class MarkdownPreview { vscode.window.showWarningMessage(localize('onPreviewStyleLoadError', "Could not load 'markdown.styles': {0}", e.body.unloadedStyles.join(', '))); break; } - }, null, this.disposables); + }, null, this._disposables); vscode.workspace.onDidChangeTextDocument(event => { if (this.isPreviewOf(event.document.uri)) { this.refresh(); } - }, null, this.disposables); + }, null, this._disposables); topmostLineMonitor.onDidChangeTopmostLine(event => { if (this.isPreviewOf(event.resource)) { this.updateForView(event.resource, event.line); } - }, null, this.disposables); + }, null, this._disposables); vscode.window.onDidChangeTextEditorSelection(event => { if (this.isPreviewOf(event.textEditor.document.uri)) { @@ -213,13 +235,13 @@ export class MarkdownPreview { source: this.resource.toString() }); } - }, null, this.disposables); + }, null, this._disposables); vscode.window.onDidChangeActiveTextEditor(editor => { if (editor && isMarkdownFile(editor.document) && !this._locked) { this.update(editor.document.uri); } - }, null, this.disposables); + }, null, this._disposables); } private readonly _onDisposeEmitter = new vscode.EventEmitter(); @@ -232,28 +254,32 @@ export class MarkdownPreview { return this._resource; } + public get resourceColumn(): vscode.ViewColumn { + return this._resourceColumn; + } + public get state() { return { resource: this.resource.toString(), locked: this._locked, line: this.line, + resourceColumn: this.resourceColumn, imageInfo: this.imageInfo }; } public dispose() { + super.dispose(); if (this._disposed) { return; } this._disposed = true; this._onDisposeEmitter.fire(); - this._onDisposeEmitter.dispose(); + this._onDidChangeViewStateEmitter.dispose(); this.editor.dispose(); - - disposeAll(this.disposables); } public update(resource: vscode.Uri) { @@ -328,10 +354,10 @@ export class MarkdownPreview { } private get iconPath() { - const root = path.join(this._contributions.extensionPath, 'media'); + const root = path.join(this._contributionProvider.extensionPath, 'media'); return { - light: vscode.Uri.file(path.join(root, 'Preview.svg')), - dark: vscode.Uri.file(path.join(root, 'Preview_inverse.svg')) + light: vscode.Uri.file(path.join(root, 'preview-light.svg')), + dark: vscode.Uri.file(path.join(root, 'preview-dark.svg')) }; } @@ -373,27 +399,51 @@ export class MarkdownPreview { } private async doUpdate(): Promise { - const resource = this._resource; + if (this._disposed) { + return; + } + + const markdownResource = this._resource; clearTimeout(this.throttleTimer); this.throttleTimer = undefined; - const document = await vscode.workspace.openTextDocument(resource); - if (!this.forceUpdate && this.currentVersion && this.currentVersion.resource.fsPath === resource.fsPath && this.currentVersion.version === document.version) { + let document: vscode.TextDocument; + try { + document = await vscode.workspace.openTextDocument(markdownResource); + } catch { + await this.showFileNotFoundError(); + return; + } + + if (this._disposed) { + return; + } + + const pendingVersion = new PreviewDocumentVersion(markdownResource, document.version); + if (!this.forceUpdate && this.currentVersion && this.currentVersion.equals(pendingVersion)) { if (this.line) { - this.updateForView(resource, this.line); + this.updateForView(markdownResource, this.line); } return; } this.forceUpdate = false; - this.currentVersion = { resource, version: document.version }; - const content = await this._contentProvider.provideTextDocumentContent(document, this._previewConfigurations, this.line, this.state); - if (this._resource === resource) { - this.editor.title = MarkdownPreview.getPreviewTitle(this._resource, this._locked); - this.editor.iconPath = this.iconPath; - this.editor.webview.options = MarkdownPreview.getWebviewOptions(resource, this._contributions); - this.editor.webview.html = content; + this.currentVersion = pendingVersion; + if (this._resource === markdownResource) { + const self = this; + const resourceProvider: WebviewResourceProvider = { + toWebviewResource: (resource) => { + return this.editor.webview.toWebviewResource(normalizeResource(markdownResource, resource)); + }, + get cspSource() { return self.editor.webview.cspSource; } + }; + const content = await this._contentProvider.provideTextDocumentContent(document, resourceProvider, this._previewConfigurations, this.line, this.state); + // Another call to `doUpdate` may have happened. + // Make sure we are still updating for the correct document + if (this.currentVersion && this.currentVersion.equals(pendingVersion)) { + this.setContent(content); + } } } @@ -408,21 +458,19 @@ export class MarkdownPreview { } private static getLocalResourceRoots( - resource: vscode.Uri, + base: vscode.Uri, contributions: MarkdownContributions - ): vscode.Uri[] { - const baseRoots = contributions.previewResourceRoots; + ): ReadonlyArray { + const baseRoots = Array.from(contributions.previewResourceRoots); - const folder = vscode.workspace.getWorkspaceFolder(resource); + const folder = vscode.workspace.getWorkspaceFolder(base); if (folder) { - return baseRoots.concat(folder.uri); + baseRoots.push(folder.uri); + } else if (!base.scheme || base.scheme === 'file') { + baseRoots.push(vscode.Uri.file(path.dirname(base.fsPath))); } - if (!resource.scheme || resource.scheme === 'file') { - return baseRoots.concat(vscode.Uri.file(path.dirname(resource.fsPath))); - } - - return baseRoots; + return baseRoots.map(root => normalizeResource(base, root)); } private onDidScrollPreview(line: number) { @@ -453,7 +501,22 @@ export class MarkdownPreview { } } - vscode.workspace.openTextDocument(this._resource).then(vscode.window.showTextDocument); + vscode.workspace.openTextDocument(this._resource) + .then(vscode.window.showTextDocument) + .then(undefined, () => { + vscode.window.showErrorMessage(localize('preview.clickOpenFailed', 'Could not open {0}', this._resource.toString())); + }); + } + + private async showFileNotFoundError() { + this.setContent(this._contentProvider.provideFileNotFoundContent(this._resource)); + } + + private setContent(html: string): void { + this.editor.title = MarkdownPreview.getPreviewTitle(this._resource, this._locked); + this.editor.iconPath = this.iconPath; + this.editor.webview.options = MarkdownPreview.getWebviewOptions(this._resource, this._contributionProvider.contributions); + this.editor.webview.html = html; } private async onDidClickPreviewLink(path: string, fragment: string | undefined) { diff --git a/extensions/markdown-language-features/src/features/previewConfig.ts b/extensions/markdown-language-features/src/features/previewConfig.ts index d660bf10793..ed09a9ce46e 100644 --- a/extensions/markdown-language-features/src/features/previewConfig.ts +++ b/extensions/markdown-language-features/src/features/previewConfig.ts @@ -12,7 +12,6 @@ export class MarkdownPreviewConfiguration { public readonly scrollBeyondLastLine: boolean; public readonly wordWrap: boolean; - public readonly previewFrontMatter: string; public readonly lineBreaks: boolean; public readonly doubleClickToSwitchToEditor: boolean; public readonly scrollEditorWithPreview: boolean; @@ -36,7 +35,6 @@ export class MarkdownPreviewConfiguration { this.wordWrap = markdownEditorConfig['editor.wordWrap'] !== 'off'; } - this.previewFrontMatter = markdownConfig.get('previewFrontMatter', 'hide'); this.scrollPreviewWithEditor = !!markdownConfig.get('preview.scrollPreviewWithEditor', true); this.scrollEditorWithPreview = !!markdownConfig.get('preview.scrollEditorWithPreview', true); this.lineBreaks = !!markdownConfig.get('preview.breaks', false); diff --git a/extensions/markdown-language-features/src/features/previewContentProvider.ts b/extensions/markdown-language-features/src/features/previewContentProvider.ts index 403fc9249d8..17b6d4f4ebb 100644 --- a/extensions/markdown-language-features/src/features/previewContentProvider.ts +++ b/extensions/markdown-language-features/src/features/previewContentProvider.ts @@ -3,17 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; import * as path from 'path'; -import { MarkdownEngine } from '../markdownEngine'; - +import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -const localize = nls.loadMessageBundle(); - import { Logger } from '../logger'; +import { MarkdownEngine } from '../markdownEngine'; +import { MarkdownContributionProvider } from '../markdownExtensions'; import { ContentSecurityPolicyArbiter, MarkdownPreviewSecurityLevel } from '../security'; -import { MarkdownPreviewConfigurationManager, MarkdownPreviewConfiguration } from './previewConfig'; -import { MarkdownContributions } from '../markdownExtensions'; +import { WebviewResourceProvider } from '../util/resources'; +import { MarkdownPreviewConfiguration, MarkdownPreviewConfigurationManager } from './previewConfig'; + +const localize = nls.loadMessageBundle(); /** * Strings used inside the markdown preview. @@ -35,17 +35,22 @@ const previewStrings = { 'Content Disabled Security Warning') }; +function escapeAttribute(value: string | vscode.Uri): string { + return value.toString().replace(/"/g, '"'); +} + export class MarkdownContentProvider { constructor( private readonly engine: MarkdownEngine, private readonly context: vscode.ExtensionContext, private readonly cspArbiter: ContentSecurityPolicyArbiter, - private readonly contributions: MarkdownContributions, + private readonly contributionProvider: MarkdownContributionProvider, private readonly logger: Logger ) { } public async provideTextDocumentContent( markdownDocument: vscode.TextDocument, + resourceProvider: WebviewResourceProvider, previewConfigurations: MarkdownPreviewConfigurationManager, initialLine: number | undefined = undefined, state?: any @@ -59,92 +64,98 @@ export class MarkdownContentProvider { scrollPreviewWithEditor: config.scrollPreviewWithEditor, scrollEditorWithPreview: config.scrollEditorWithPreview, doubleClickToSwitchToEditor: config.doubleClickToSwitchToEditor, - disableSecurityWarnings: this.cspArbiter.shouldDisableSecurityWarnings() + disableSecurityWarnings: this.cspArbiter.shouldDisableSecurityWarnings(), + webviewResourceRoot: resourceProvider.toWebviewResource(markdownDocument.uri).toString(), }; this.logger.log('provideTextDocumentContent', initialData); // Content Security Policy const nonce = new Date().getTime() + '' + new Date().getMilliseconds(); - const csp = this.getCspForResource(sourceUri, nonce); + const csp = this.getCsp(resourceProvider, sourceUri, nonce); - const body = await this.engine.render(markdownDocument, config.previewFrontMatter === 'hide'); + const body = await this.engine.render(markdownDocument); return ` - + ${csp} - - ${this.getStyles(sourceUri, nonce, config, state)} - + data-settings="${escapeAttribute(JSON.stringify(initialData))}" + data-strings="${escapeAttribute(JSON.stringify(previewStrings))}" + data-state="${escapeAttribute(JSON.stringify(state || {}))}"> + + ${this.getStyles(resourceProvider, sourceUri, config, state)} + ${body}
    - ${this.getScripts(nonce)} + ${this.getScripts(resourceProvider, nonce)} `; } - private extensionResourcePath(mediaFile: string): string { - return vscode.Uri.file(this.context.asAbsolutePath(path.join('media', mediaFile))) - .with({ scheme: 'vscode-resource' }) - .toString(); + public provideFileNotFoundContent( + resource: vscode.Uri, + ): string { + const resourcePath = path.basename(resource.fsPath); + const body = localize('preview.notFound', '{0} cannot be found', resourcePath); + return ` + + + ${body} + + `; } - private fixHref(resource: vscode.Uri, href: string): string { + private extensionResourcePath(resourceProvider: WebviewResourceProvider, mediaFile: string): string { + const webviewResource = resourceProvider.toWebviewResource( + vscode.Uri.file(this.context.asAbsolutePath(path.join('media', mediaFile)))); + return webviewResource.toString(); + } + + private fixHref(resourceProvider: WebviewResourceProvider, resource: vscode.Uri, href: string): string { if (!href) { return href; } - // Use href if it is already an URL - const hrefUri = vscode.Uri.parse(href); - if (['http', 'https'].indexOf(hrefUri.scheme) >= 0) { - return hrefUri.toString(true); + if (href.startsWith('http:') || href.startsWith('https:') || href.startsWith('file:')) { + return href; } - // Use href as file URI if it is absolute - if (path.isAbsolute(href) || hrefUri.scheme === 'file') { - return vscode.Uri.file(href) - .with({ scheme: 'vscode-resource' }) - .toString(); + // Assume it must be a local file + if (path.isAbsolute(href)) { + return resourceProvider.toWebviewResource(vscode.Uri.file(href)).toString(); } // Use a workspace relative path if there is a workspace - let root = vscode.workspace.getWorkspaceFolder(resource); + const root = vscode.workspace.getWorkspaceFolder(resource); if (root) { - return vscode.Uri.file(path.join(root.uri.fsPath, href)) - .with({ scheme: 'vscode-resource' }) - .toString(); + return resourceProvider.toWebviewResource(vscode.Uri.file(path.join(root.uri.fsPath, href))).toString(); } // Otherwise look relative to the markdown file - return vscode.Uri.file(path.join(path.dirname(resource.fsPath), href)) - .with({ scheme: 'vscode-resource' }) - .toString(); + return resourceProvider.toWebviewResource(vscode.Uri.file(path.join(path.dirname(resource.fsPath), href))).toString(); } - private computeCustomStyleSheetIncludes(resource: vscode.Uri, config: MarkdownPreviewConfiguration): string { - if (Array.isArray(config.styles)) { - return config.styles.map(style => { - return ``; - }).join('\n'); + private computeCustomStyleSheetIncludes(resourceProvider: WebviewResourceProvider, resource: vscode.Uri, config: MarkdownPreviewConfiguration): string { + if (!Array.isArray(config.styles)) { + return ''; } - return ''; + const out: string[] = []; + for (const style of config.styles) { + out.push(``); + } + return out.join('\n'); } - private getSettingsOverrideStyles(nonce: string, config: MarkdownPreviewConfiguration): string { - return ``; + private getSettingsOverrideStyles(config: MarkdownPreviewConfiguration): string { + return [ + config.fontFamily ? `--vscode-markdown-font-family: ${config.fontFamily};` : '', + isNaN(config.fontSize) ? '' : `--vscode-markdown-font-size: ${config.fontSize}px;`, + isNaN(config.lineHeight) ? '' : `--vscode-markdown-line-height: ${config.lineHeight};`, + ].join(' '); } private getImageStabilizerStyles(state?: any) { @@ -162,37 +173,47 @@ export class MarkdownContentProvider { return ret; } - private getStyles(resource: vscode.Uri, nonce: string, config: MarkdownPreviewConfiguration, state?: any): string { - const baseStyles = this.contributions.previewStyles - .map(resource => ``) - .join('\n'); + private getStyles(resourceProvider: WebviewResourceProvider, resource: vscode.Uri, config: MarkdownPreviewConfiguration, state?: any): string { + const baseStyles: string[] = []; + for (const resource of this.contributionProvider.contributions.previewStyles) { + baseStyles.push(``); + } - return `${baseStyles} - ${this.getSettingsOverrideStyles(nonce, config)} - ${this.computeCustomStyleSheetIncludes(resource, config)} + return `${baseStyles.join('\n')} + ${this.computeCustomStyleSheetIncludes(resourceProvider, resource, config)} ${this.getImageStabilizerStyles(state)}`; } - private getScripts(nonce: string): string { - return this.contributions.previewScripts - .map(resource => ``) - .join('\n'); + private getScripts(resourceProvider: WebviewResourceProvider, nonce: string): string { + const out: string[] = []; + for (const resource of this.contributionProvider.contributions.previewScripts) { + out.push(``); + } + return out.join('\n'); } - private getCspForResource(resource: vscode.Uri, nonce: string): string { + private getCsp( + provider: WebviewResourceProvider, + resource: vscode.Uri, + nonce: string + ): string { + const rule = provider.cspSource; switch (this.cspArbiter.getSecurityLevelForResource(resource)) { case MarkdownPreviewSecurityLevel.AllowInsecureContent: - return ``; + return ``; case MarkdownPreviewSecurityLevel.AllowInsecureLocalContent: - return ``; + return ``; case MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent: return ''; case MarkdownPreviewSecurityLevel.Strict: default: - return ``; + return ``; } } } diff --git a/extensions/markdown-language-features/src/features/previewManager.ts b/extensions/markdown-language-features/src/features/previewManager.ts index 15e414f762e..3fc8106908b 100644 --- a/extensions/markdown-language-features/src/features/previewManager.ts +++ b/extensions/markdown-language-features/src/features/previewManager.ts @@ -5,33 +5,33 @@ import * as vscode from 'vscode'; import { Logger } from '../logger'; -import { MarkdownContributions } from '../markdownExtensions'; -import { disposeAll } from '../util/dispose'; +import { MarkdownContributionProvider } from '../markdownExtensions'; +import { disposeAll, Disposable } from '../util/dispose'; import { MarkdownFileTopmostLineMonitor } from '../util/topmostLineMonitor'; import { MarkdownPreview, PreviewSettings } from './preview'; import { MarkdownPreviewConfigurationManager } from './previewConfig'; import { MarkdownContentProvider } from './previewContentProvider'; -export class MarkdownPreviewManager implements vscode.WebviewPanelSerializer { +export class MarkdownPreviewManager extends Disposable implements vscode.WebviewPanelSerializer { private static readonly markdownPreviewActiveContextKey = 'markdownPreviewFocus'; private readonly _topmostLineMonitor = new MarkdownFileTopmostLineMonitor(); private readonly _previewConfigurations = new MarkdownPreviewConfigurationManager(); private readonly _previews: MarkdownPreview[] = []; private _activePreview: MarkdownPreview | undefined = undefined; - private readonly _disposables: vscode.Disposable[] = []; public constructor( private readonly _contentProvider: MarkdownContentProvider, private readonly _logger: Logger, - private readonly _contributions: MarkdownContributions + private readonly _contributions: MarkdownContributionProvider ) { - this._disposables.push(vscode.window.registerWebviewPanelSerializer(MarkdownPreview.viewType, this)); + super(); + this._register(vscode.window.registerWebviewPanelSerializer(MarkdownPreview.viewType, this)); } public dispose(): void { - disposeAll(this._disposables); + super.dispose(); disposeAll(this._previews); } @@ -65,6 +65,10 @@ export class MarkdownPreviewManager implements vscode.WebviewPanelSerializer { return this._activePreview && this._activePreview.resource; } + public get activePreviewResourceColumn() { + return this._activePreview && this._activePreview.resourceColumn; + } + public toggleLock() { const preview = this._activePreview; if (preview) { @@ -110,6 +114,7 @@ export class MarkdownPreviewManager implements vscode.WebviewPanelSerializer { const preview = MarkdownPreview.create( resource, previewSettings.previewColumn, + previewSettings.resourceColumn, previewSettings.locked, this._contentProvider, this._previewConfigurations, diff --git a/extensions/markdown-language-features/src/features/workspaceSymbolProvider.ts b/extensions/markdown-language-features/src/features/workspaceSymbolProvider.ts index 12e51c75d76..fe886423aa0 100644 --- a/extensions/markdown-language-features/src/features/workspaceSymbolProvider.ts +++ b/extensions/markdown-language-features/src/features/workspaceSymbolProvider.ts @@ -4,11 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { disposeAll } from '../util/dispose'; +import { Disposable } from '../util/dispose'; import { isMarkdownFile } from '../util/file'; import { Lazy, lazy } from '../util/lazy'; import MDDocumentSymbolProvider from './documentSymbolProvider'; import { SkinnyTextDocument } from '../tableOfContentsProvider'; +import { flatten } from '../util/arrays'; export interface WorkspaceMarkdownDocumentProvider { getAllMarkdownDocuments(): Thenable>; @@ -18,25 +19,13 @@ export interface WorkspaceMarkdownDocumentProvider { readonly onDidDeleteMarkdownDocument: vscode.Event; } -class VSCodeWorkspaceMarkdownDocumentProvider implements WorkspaceMarkdownDocumentProvider { +class VSCodeWorkspaceMarkdownDocumentProvider extends Disposable implements WorkspaceMarkdownDocumentProvider { - private readonly _onDidChangeMarkdownDocumentEmitter = new vscode.EventEmitter(); - private readonly _onDidCreateMarkdownDocumentEmitter = new vscode.EventEmitter(); - private readonly _onDidDeleteMarkdownDocumentEmitter = new vscode.EventEmitter(); + private readonly _onDidChangeMarkdownDocumentEmitter = this._register(new vscode.EventEmitter()); + private readonly _onDidCreateMarkdownDocumentEmitter = this._register(new vscode.EventEmitter()); + private readonly _onDidDeleteMarkdownDocumentEmitter = this._register(new vscode.EventEmitter()); private _watcher: vscode.FileSystemWatcher | undefined; - private _disposables: vscode.Disposable[] = []; - - public dispose() { - this._onDidChangeMarkdownDocumentEmitter.dispose(); - this._onDidDeleteMarkdownDocumentEmitter.dispose(); - - if (this._watcher) { - this._watcher.dispose(); - } - - disposeAll(this._disposables); - } async getAllMarkdownDocuments() { const resources = await vscode.workspace.findFiles('**/*.md', '**/node_modules/**'); @@ -64,7 +53,7 @@ class VSCodeWorkspaceMarkdownDocumentProvider implements WorkspaceMarkdownDocume return; } - this._watcher = vscode.workspace.createFileSystemWatcher('**/*.md'); + this._watcher = this._register(vscode.workspace.createFileSystemWatcher('**/*.md')); this._watcher.onDidChange(async resource => { const document = await this.getMarkdownDocument(resource); @@ -98,15 +87,16 @@ class VSCodeWorkspaceMarkdownDocumentProvider implements WorkspaceMarkdownDocume } -export default class MarkdownWorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvider { +export default class MarkdownWorkspaceSymbolProvider extends Disposable implements vscode.WorkspaceSymbolProvider { private _symbolCache = new Map>>(); private _symbolCachePopulated: boolean = false; - private _disposables: vscode.Disposable[] = []; public constructor( private _symbolProvider: MDDocumentSymbolProvider, private _workspaceMarkdownDocumentProvider: WorkspaceMarkdownDocumentProvider = new VSCodeWorkspaceMarkdownDocumentProvider() - ) { } + ) { + super(); + } public async provideWorkspaceSymbols(query: string): Promise { if (!this._symbolCachePopulated) { @@ -119,7 +109,7 @@ export default class MarkdownWorkspaceSymbolProvider implements vscode.Workspace } const allSymbolsSets = await Promise.all(Array.from(this._symbolCache.values()).map(x => x.value)); - const allSymbols: vscode.SymbolInformation[] = Array.prototype.concat.apply([], allSymbolsSets); + const allSymbols = flatten(allSymbolsSets); return allSymbols.filter(symbolInformation => symbolInformation.name.toLowerCase().indexOf(query.toLowerCase()) !== -1); } @@ -130,10 +120,6 @@ export default class MarkdownWorkspaceSymbolProvider implements vscode.Workspace } } - public dispose(): void { - disposeAll(this._disposables); - } - private getSymbols(document: SkinnyTextDocument): Lazy> { return lazy(async () => { return this._symbolProvider.provideDocumentSymbolInformation(document); diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts index 9ad45ea3dd2..0cc75bfe823 100644 --- a/extensions/markdown-language-features/src/markdownEngine.ts +++ b/extensions/markdown-language-features/src/markdownEngine.ts @@ -7,124 +7,161 @@ import * as crypto from 'crypto'; import { MarkdownIt, Token } from 'markdown-it'; import * as path from 'path'; import * as vscode from 'vscode'; -import { MarkdownContributions } from './markdownExtensions'; +import { MarkdownContributionProvider as MarkdownContributionProvider } from './markdownExtensions'; import { Slugifier } from './slugify'; import { SkinnyTextDocument } from './tableOfContentsProvider'; import { getUriForLinkWithKnownExternalScheme } from './util/links'; -const FrontMatterRegex = /^---\s*[^]*?(-{3}|\.{3})\s*/; +const UNICODE_NEWLINE_REGEX = /\u2028|\u2029/g; + +interface MarkdownItConfig { + readonly breaks: boolean; + readonly linkify: boolean; +} + +class TokenCache { + private cachedDocument?: { + readonly uri: vscode.Uri; + readonly version: number; + readonly config: MarkdownItConfig; + }; + private tokens?: Token[]; + + public tryGetCached(document: SkinnyTextDocument, config: MarkdownItConfig): Token[] | undefined { + if (this.cachedDocument + && this.cachedDocument.uri.toString() === document.uri.toString() + && this.cachedDocument.version === document.version + && this.cachedDocument.config.breaks === config.breaks + && this.cachedDocument.config.linkify === config.linkify + ) { + return this.tokens; + } + return undefined; + } + + public update(document: SkinnyTextDocument, config: MarkdownItConfig, tokens: Token[]) { + this.cachedDocument = { + uri: document.uri, + version: document.version, + config, + }; + this.tokens = tokens; + } + + public clean(): void { + this.cachedDocument = undefined; + this.tokens = undefined; + } +} export class MarkdownEngine { - private md?: MarkdownIt; + private md?: Promise; - private firstLine?: number; private currentDocument?: vscode.Uri; private _slugCount = new Map(); + private _tokenCache = new TokenCache(); public constructor( - private readonly extensionPreviewResourceProvider: MarkdownContributions, + private readonly contributionProvider: MarkdownContributionProvider, private readonly slugifier: Slugifier, - ) { } - - private usePlugin(factory: (md: any) => any): void { - try { - this.md = factory(this.md); - } catch (e) { - // noop - } - } - - private async getEngine(resource: vscode.Uri): Promise { - if (!this.md) { - const hljs = await import('highlight.js'); - this.md = (await import('markdown-it'))({ - html: true, - highlight: (str: string, lang?: string) => { - // Workaround for highlight not supporting tsx: https://github.com/isagalaev/highlight.js/issues/1155 - if (lang && ['tsx', 'typescriptreact'].indexOf(lang.toLocaleLowerCase()) >= 0) { - lang = 'jsx'; - } - if (lang && lang.toLocaleLowerCase() === 'json5') { - lang = 'json'; - } - if (lang && lang.toLocaleLowerCase() === 'c#') { - lang = 'cs'; - } - if (lang && hljs.getLanguage(lang)) { - try { - return `
    ${hljs.highlight(lang, str, true).value}
    `; - } catch (error) { } - } - return `
    ${this.md!.utils.escapeHtml(str)}
    `; - } - }); - - for (const plugin of this.extensionPreviewResourceProvider.markdownItPlugins) { - this.usePlugin(await plugin); - } - - for (const renderName of ['paragraph_open', 'heading_open', 'image', 'code_block', 'fence', 'blockquote_open', 'list_item_open']) { - this.addLineNumberRenderer(this.md, renderName); - } - - this.addImageStabilizer(this.md); - this.addFencedRenderer(this.md); - - this.addLinkNormalizer(this.md); - this.addLinkValidator(this.md); - this.addNamedHeaders(this.md); - } - - const config = vscode.workspace.getConfiguration('markdown', resource); - this.md.set({ - breaks: config.get('preview.breaks', false), - linkify: config.get('preview.linkify', true) + ) { + contributionProvider.onContributionsChanged(() => { + // Markdown plugin contributions may have changed + this.md = undefined; }); - return this.md; } - private stripFrontmatter(text: string): { text: string, offset: number } { - let offset = 0; - const frontMatterMatch = FrontMatterRegex.exec(text); - if (frontMatterMatch) { - const frontMatter = frontMatterMatch[0]; - offset = frontMatter.split(/\r\n|\n|\r/g).length - 1; - text = text.substr(frontMatter.length); + private async getEngine(config: MarkdownItConfig): Promise { + if (!this.md) { + this.md = import('markdown-it').then(async markdownIt => { + let md: MarkdownIt = markdownIt(await getMarkdownOptions(() => md)); + + for (const plugin of this.contributionProvider.contributions.markdownItPlugins.values()) { + try { + md = (await plugin)(md); + } catch { + // noop + } + } + + const frontMatterPlugin = require('markdown-it-front-matter'); + // Extract rules from front matter plugin and apply at a lower precedence + let fontMatterRule: any; + frontMatterPlugin({ + block: { + ruler: { + before: (_id: any, _id2: any, rule: any) => { fontMatterRule = rule; } + } + } + }, () => { /* noop */ }); + + md.block.ruler.before('fence', 'front_matter', fontMatterRule, { + alt: ['paragraph', 'reference', 'blockquote', 'list'] + }); + + for (const renderName of ['paragraph_open', 'heading_open', 'image', 'code_block', 'fence', 'blockquote_open', 'list_item_open']) { + this.addLineNumberRenderer(md, renderName); + } + + this.addImageStabilizer(md); + this.addFencedRenderer(md); + + this.addLinkNormalizer(md); + this.addLinkValidator(md); + this.addNamedHeaders(md); + return md; + }); } - return { text, offset }; + + const md = await this.md!; + md.set(config); + return md; } - public async render(document: SkinnyTextDocument, stripFrontmatter: boolean): Promise { - let offset = 0; - let text = document.getText(); - if (stripFrontmatter) { - const markdownContent = this.stripFrontmatter(text); - offset = markdownContent.offset; - text = markdownContent.text; + private tokenize( + document: SkinnyTextDocument, + config: MarkdownItConfig, + engine: MarkdownIt + ): Token[] { + const cached = this._tokenCache.tryGetCached(document, config); + if (cached) { + return cached; } + this.currentDocument = document.uri; - this.firstLine = offset; this._slugCount = new Map(); - const engine = await this.getEngine(document.uri); - return engine.render(text); + const text = document.getText(); + const tokens = engine.parse(text.replace(UNICODE_NEWLINE_REGEX, ''), {}); + this._tokenCache.update(document, config, tokens); + return tokens; + } + + public async render(document: SkinnyTextDocument): Promise { + const config = this.getConfig(document.uri); + const engine = await this.getEngine(config); + return engine.renderer.render(this.tokenize(document, config, engine), { + ...(engine as any).options, + ...config + }, {}); } public async parse(document: SkinnyTextDocument): Promise { - const UNICODE_NEWLINE_REGEX = /\u2028|\u2029/g; - const { text, offset } = this.stripFrontmatter(document.getText()); - this.currentDocument = document.uri; - this._slugCount = new Map(); + const config = this.getConfig(document.uri); + const engine = await this.getEngine(config); + return this.tokenize(document, config, engine); + } - const engine = await this.getEngine(document.uri); + public cleanCache(): void { + this._tokenCache.clean(); + } - return engine.parse(text.replace(UNICODE_NEWLINE_REGEX, ''), {}).map(token => { - if (token.map) { - token.map[0] += offset; - token.map[1] += offset; - } - return token; - }); + private getConfig(resource: vscode.Uri): MarkdownItConfig { + const config = vscode.workspace.getConfiguration('markdown', resource); + return { + breaks: config.get('preview.breaks', false), + linkify: config.get('preview.linkify', true) + }; } private addLineNumberRenderer(md: any, ruleName: string): void { @@ -132,7 +169,7 @@ export class MarkdownEngine { md.renderer.rules[ruleName] = (tokens: any, idx: number, options: any, env: any, self: any) => { const token = tokens[idx]; if (token.map && token.map.length) { - token.attrSet('data-line', this.firstLine + token.map[0]); + token.attrSet('data-line', token.map[0]); token.attrJoin('class', 'code-line'); } @@ -188,7 +225,6 @@ export class MarkdownEngine { return normalizeLink(externalSchemeUri.toString(true)); } - // Assume it must be an relative or absolute file path // Use a fake scheme to avoid parse warnings let uri = vscode.Uri.parse(`vscode-resource:${link}`); @@ -225,7 +261,7 @@ export class MarkdownEngine { const validateLink = md.validateLink; md.validateLink = (link: string) => { // support file:// links - return validateLink(link) || link.indexOf('file:') === 0; + return validateLink(link) || link.startsWith('file:') || /^data:image\/.*?;/.test(link); }; } @@ -253,4 +289,30 @@ export class MarkdownEngine { } }; } -} \ No newline at end of file +} + +async function getMarkdownOptions(md: () => MarkdownIt) { + const hljs = await import('highlight.js'); + return { + html: true, + highlight: (str: string, lang?: string) => { + // Workaround for highlight not supporting tsx: https://github.com/isagalaev/highlight.js/issues/1155 + if (lang && ['tsx', 'typescriptreact'].indexOf(lang.toLocaleLowerCase()) >= 0) { + lang = 'jsx'; + } + if (lang && lang.toLocaleLowerCase() === 'json5') { + lang = 'json'; + } + if (lang && lang.toLocaleLowerCase() === 'c#') { + lang = 'cs'; + } + if (lang && hljs.getLanguage(lang)) { + try { + return `
    ${hljs.highlight(lang, str, true).value}
    `; + } + catch (error) { } + } + return `
    ${md().utils.escapeHtml(str)}
    `; + } + }; +} diff --git a/extensions/markdown-language-features/src/markdownExtensions.ts b/extensions/markdown-language-features/src/markdownExtensions.ts index 55c8d76e7a4..b03c5df80bd 100644 --- a/extensions/markdown-language-features/src/markdownExtensions.ts +++ b/extensions/markdown-language-features/src/markdownExtensions.ts @@ -5,13 +5,14 @@ import * as vscode from 'vscode'; import * as path from 'path'; +import { Disposable } from './util/dispose'; +import * as arrays from './util/arrays'; const resolveExtensionResource = (extension: vscode.Extension, resourcePath: string): vscode.Uri => { - return vscode.Uri.file(path.join(extension.extensionPath, resourcePath)) - .with({ scheme: 'vscode-resource' }); + return vscode.Uri.file(path.join(extension.extensionPath, resourcePath)); }; -const resolveExtensionResources = (extension: vscode.Extension, resourcePaths: any): vscode.Uri[] => { +const resolveExtensionResources = (extension: vscode.Extension, resourcePaths: unknown): vscode.Uri[] => { const result: vscode.Uri[] = []; if (Array.isArray(resourcePaths)) { for (const resource of resourcePaths) { @@ -26,96 +27,135 @@ const resolveExtensionResources = (extension: vscode.Extension, resourcePat }; export interface MarkdownContributions { - readonly extensionPath: string; - readonly previewScripts: vscode.Uri[]; - readonly previewStyles: vscode.Uri[]; - readonly markdownItPlugins: Thenable<(md: any) => any>[]; - readonly previewResourceRoots: vscode.Uri[]; + readonly previewScripts: ReadonlyArray; + readonly previewStyles: ReadonlyArray; + readonly previewResourceRoots: ReadonlyArray; + readonly markdownItPlugins: Map any>>; } -class MarkdownExtensionContributions implements MarkdownContributions { - private readonly _scripts: vscode.Uri[] = []; - private readonly _styles: vscode.Uri[] = []; - private readonly _previewResourceRoots: vscode.Uri[] = []; - private readonly _plugins: Thenable<(md: any) => any>[] = []; +export namespace MarkdownContributions { + export const Empty: MarkdownContributions = { + previewScripts: [], + previewStyles: [], + previewResourceRoots: [], + markdownItPlugins: new Map() + }; - private _loaded = false; - - public constructor( - public readonly extensionPath: string, - ) { } - - public get previewScripts(): vscode.Uri[] { - this.ensureLoaded(); - return this._scripts; + export function merge(a: MarkdownContributions, b: MarkdownContributions): MarkdownContributions { + return { + previewScripts: [...a.previewScripts, ...b.previewScripts], + previewStyles: [...a.previewStyles, ...b.previewStyles], + previewResourceRoots: [...a.previewResourceRoots, ...b.previewResourceRoots], + markdownItPlugins: new Map([...a.markdownItPlugins.entries(), ...b.markdownItPlugins.entries()]), + }; } - public get previewStyles(): vscode.Uri[] { - this.ensureLoaded(); - return this._styles; + function uriEqual(a: vscode.Uri, b: vscode.Uri): boolean { + return a.toString() === b.toString(); } - public get previewResourceRoots(): vscode.Uri[] { - this.ensureLoaded(); - return this._previewResourceRoots; + export function equal(a: MarkdownContributions, b: MarkdownContributions): boolean { + return arrays.equals(a.previewScripts, b.previewScripts, uriEqual) + && arrays.equals(a.previewStyles, b.previewStyles, uriEqual) + && arrays.equals(a.previewResourceRoots, b.previewResourceRoots, uriEqual) + && arrays.equals(Array.from(a.markdownItPlugins.keys()), Array.from(b.markdownItPlugins.keys())); } - public get markdownItPlugins(): Thenable<(md: any) => any>[] { - this.ensureLoaded(); - return this._plugins; - } - - private ensureLoaded() { - if (this._loaded) { - return; + export function fromExtension( + extension: vscode.Extension + ): MarkdownContributions { + const contributions = extension.packageJSON && extension.packageJSON.contributes; + if (!contributions) { + return MarkdownContributions.Empty; } - this._loaded = true; - for (const extension of vscode.extensions.all) { - const contributes = extension.packageJSON && extension.packageJSON.contributes; - if (!contributes) { - continue; - } + const previewStyles = getContributedStyles(contributions, extension); + const previewScripts = getContributedScripts(contributions, extension); + const previewResourceRoots = previewStyles.length || previewScripts.length ? [vscode.Uri.file(extension.extensionPath)] : []; + const markdownItPlugins = getContributedMarkdownItPlugins(contributions, extension); - this.tryLoadPreviewStyles(contributes, extension); - this.tryLoadPreviewScripts(contributes, extension); - this.tryLoadMarkdownItPlugins(contributes, extension); - - if (contributes['markdown.previewScripts'] || contributes['markdown.previewStyles']) { - this._previewResourceRoots.push(vscode.Uri.file(extension.extensionPath)); - } - } + return { + previewScripts, + previewStyles, + previewResourceRoots, + markdownItPlugins + }; } - private tryLoadMarkdownItPlugins( + function getContributedMarkdownItPlugins( contributes: any, extension: vscode.Extension - ) { + ): Map any>> { + const map = new Map any>>(); if (contributes['markdown.markdownItPlugins']) { - this._plugins.push(extension.activate().then(() => { + map.set(extension.id, extension.activate().then(() => { if (extension.exports && extension.exports.extendMarkdownIt) { return (md: any) => extension.exports.extendMarkdownIt(md); } return (md: any) => md; })); } + return map; } - private tryLoadPreviewScripts( + function getContributedScripts( contributes: any, extension: vscode.Extension ) { - this._scripts.push(...resolveExtensionResources(extension, contributes['markdown.previewScripts'])); + return resolveExtensionResources(extension, contributes['markdown.previewScripts']); } - private tryLoadPreviewStyles( + function getContributedStyles( contributes: any, extension: vscode.Extension ) { - this._styles.push(...resolveExtensionResources(extension, contributes['markdown.previewStyles'])); + return resolveExtensionResources(extension, contributes['markdown.previewStyles']); } } -export function getMarkdownExtensionContributions(context: vscode.ExtensionContext): MarkdownContributions { - return new MarkdownExtensionContributions(context.extensionPath); +export interface MarkdownContributionProvider { + readonly extensionPath: string; + readonly contributions: MarkdownContributions; + readonly onContributionsChanged: vscode.Event; + + dispose(): void; +} + +class VSCodeExtensionMarkdownContributionProvider extends Disposable implements MarkdownContributionProvider { + private _contributions?: MarkdownContributions; + + public constructor( + public readonly extensionPath: string, + ) { + super(); + + vscode.extensions.onDidChange(() => { + const currentContributions = this.getCurrentContributions(); + const existingContributions = this._contributions || MarkdownContributions.Empty; + if (!MarkdownContributions.equal(existingContributions, currentContributions)) { + this._contributions = currentContributions; + this._onContributionsChanged.fire(this); + } + }, undefined, this._disposables); + } + + private readonly _onContributionsChanged = this._register(new vscode.EventEmitter()); + public readonly onContributionsChanged = this._onContributionsChanged.event; + + public get contributions(): MarkdownContributions { + if (!this._contributions) { + this._contributions = this.getCurrentContributions(); + } + return this._contributions; + } + + private getCurrentContributions(): MarkdownContributions { + return vscode.extensions.all + .map(MarkdownContributions.fromExtension) + .reduce(MarkdownContributions.merge, MarkdownContributions.Empty); + } +} + +export function getMarkdownExtensionContributions(context: vscode.ExtensionContext): MarkdownContributionProvider { + return new VSCodeExtensionMarkdownContributionProvider(context.extensionPath); } \ No newline at end of file diff --git a/extensions/markdown-language-features/src/security.ts b/extensions/markdown-language-features/src/security.ts index 7f11d65a113..89a9667e134 100644 --- a/extensions/markdown-language-features/src/security.ts +++ b/extensions/markdown-language-features/src/security.ts @@ -94,7 +94,7 @@ export class PreviewSecuritySelector { private readonly webviewManager: MarkdownPreviewManager ) { } - public async showSecutitySelectorForResource(resource: vscode.Uri): Promise { + public async showSecuritySelectorForResource(resource: vscode.Uri): Promise { interface PreviewSecurityPickItem extends vscode.QuickPickItem { readonly type: 'moreinfo' | 'toggle' | MarkdownPreviewSecurityLevel; } diff --git a/extensions/markdown-language-features/src/slugify.ts b/extensions/markdown-language-features/src/slugify.ts index 5b9146b602f..a91c5126a22 100644 --- a/extensions/markdown-language-features/src/slugify.ts +++ b/extensions/markdown-language-features/src/slugify.ts @@ -23,7 +23,7 @@ export const githubSlugifier: Slugifier = new class implements Slugifier { heading.trim() .toLowerCase() .replace(/\s+/g, '-') // Replace whitespace with - - .replace(/[\]\[\!\'\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~\`。,、;:?!…—·ˉ¨‘’“”々~‖∶"'`|〃〔〕〈〉《》「」『』.〖〗【】()[]{}]/g, '') // Remove known punctuators + .replace(/[\]\[\!\'\#\$\%\&\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~\`。,、;:?!…—·ˉ¨‘’“”々~‖∶"'`|〃〔〕〈〉《》「」『』.〖〗【】()[]{}]/g, '') // Remove known punctuators .replace(/^\-+/, '') // Remove leading - .replace(/\-+$/, '') // Remove trailing - ); diff --git a/extensions/markdown-language-features/src/tableOfContentsProvider.ts b/extensions/markdown-language-features/src/tableOfContentsProvider.ts index d2b041c2523..342d71f1cfe 100644 --- a/extensions/markdown-language-features/src/tableOfContentsProvider.ts +++ b/extensions/markdown-language-features/src/tableOfContentsProvider.ts @@ -17,6 +17,7 @@ export interface TocEntry { export interface SkinnyTextDocument { readonly uri: vscode.Uri; + readonly version: number; readonly lineCount: number; getText(): string; lineAt(line: number): vscode.TextLine; diff --git a/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts b/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts index 5a1d0c87880..ba6cfa2567f 100644 --- a/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts +++ b/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts @@ -72,6 +72,14 @@ suite('markdown.DocumentLinkProvider', () => { assertRangeEqual(link.range, new vscode.Range(0, 6, 0, 25)); }); + // #35245 + test('Should handle links with escaped characters in name', () => { + const links = getLinksForFile('a [b\\]](./file)'); + assert.strictEqual(links.length, 1); + const [link] = links; + assertRangeEqual(link.range, new vscode.Range(0, 8, 0, 14)); + }); + test('Should handle links with balanced parens', () => { { @@ -103,6 +111,33 @@ suite('markdown.DocumentLinkProvider', () => { assertRangeEqual(link1.range, new vscode.Range(0, 10, 0, 14)); assertRangeEqual(link2.range, new vscode.Range(0, 23, 0, 28)); }); + + // #49238 + test('should handle hyperlinked images', () => { + { + const links = getLinksForFile('[![alt text](image.jpg)](https://example.com)'); + assert.strictEqual(links.length, 2); + const [link1, link2] = links; + assertRangeEqual(link1.range, new vscode.Range(0,13,0,22)); + assertRangeEqual(link2.range, new vscode.Range(0,25,0,44)); + } + { + const links = getLinksForFile('[![a]( whitespace.jpg )]( https://whitespace.com )'); + assert.strictEqual(links.length, 2); + const [link1, link2] = links; + assertRangeEqual(link1.range, new vscode.Range(0,7,0,21)); + assertRangeEqual(link2.range, new vscode.Range(0,26,0,48)); + } + { + const links = getLinksForFile('[![a](img1.jpg)](file1.txt) text [![a](img2.jpg)](file2.txt)'); + assert.strictEqual(links.length, 4); + const [link1, link2, link3, link4] = links; + assertRangeEqual(link1.range, new vscode.Range(0,6,0,14)); + assertRangeEqual(link2.range, new vscode.Range(0,17,0,26)); + assertRangeEqual(link3.range, new vscode.Range(0,39,0,47)); + assertRangeEqual(link4.range, new vscode.Range(0,50,0,59)); + } + }); }); diff --git a/extensions/markdown-language-features/src/test/engine.ts b/extensions/markdown-language-features/src/test/engine.ts index a1834e057a2..cb74a5b695f 100644 --- a/extensions/markdown-language-features/src/test/engine.ts +++ b/extensions/markdown-language-features/src/test/engine.ts @@ -5,15 +5,14 @@ import * as vscode from 'vscode'; import { MarkdownEngine } from '../markdownEngine'; -import { MarkdownContributions } from '../markdownExtensions'; +import { MarkdownContributionProvider, MarkdownContributions } from '../markdownExtensions'; import { githubSlugifier } from '../slugify'; +import { Disposable } from '../util/dispose'; -const emptyContributions = new class implements MarkdownContributions { +const emptyContributions = new class extends Disposable implements MarkdownContributionProvider { readonly extensionPath = ''; - readonly previewScripts: vscode.Uri[] = []; - readonly previewStyles: vscode.Uri[] = []; - readonly previewResourceRoots: vscode.Uri[] = []; - readonly markdownItPlugins: Promise<(md: any) => any>[] = []; + readonly contributions = MarkdownContributions.Empty; + readonly onContributionsChanged = this._register(new vscode.EventEmitter()).event; }; export function createNewMarkdownEngine(): MarkdownEngine { diff --git a/extensions/markdown-language-features/src/test/inMemoryDocument.ts b/extensions/markdown-language-features/src/test/inMemoryDocument.ts index bfcf3721b65..c2472e5a4ec 100644 --- a/extensions/markdown-language-features/src/test/inMemoryDocument.ts +++ b/extensions/markdown-language-features/src/test/inMemoryDocument.ts @@ -10,7 +10,8 @@ export class InMemoryDocument implements vscode.TextDocument { constructor( public readonly uri: vscode.Uri, - private readonly _contents: string + private readonly _contents: string, + public readonly version = 1, ) { this._lines = this._contents.split(/\n/g); } @@ -18,7 +19,6 @@ export class InMemoryDocument implements vscode.TextDocument { isUntitled: boolean = false; languageId: string = ''; - version: number = 1; isDirty: boolean = false; isClosed: boolean = false; eol: vscode.EndOfLine = vscode.EndOfLine.LF; diff --git a/extensions/markdown-language-features/src/test/workspaceSymbolProvider.test.ts b/extensions/markdown-language-features/src/test/workspaceSymbolProvider.test.ts index f5b3eb0ea4a..e74d3b592bc 100644 --- a/extensions/markdown-language-features/src/test/workspaceSymbolProvider.test.ts +++ b/extensions/markdown-language-features/src/test/workspaceSymbolProvider.test.ts @@ -38,7 +38,7 @@ suite('markdown.WorkspaceSymbolProvider', () => { const fileNameCount = 10; const files: vscode.TextDocument[] = []; for (let i = 0; i < fileNameCount; ++i) { - const testFileName = vscode.Uri.parse(`test${i}.md`); + const testFileName = vscode.Uri.file(`test${i}.md`); files.push(new InMemoryDocument(testFileName, `# common\nabc\n## header${i}`)); } @@ -52,7 +52,7 @@ suite('markdown.WorkspaceSymbolProvider', () => { const testFileName = vscode.Uri.file('test.md'); const workspaceFileProvider = new InMemoryWorkspaceMarkdownDocumentProvider([ - new InMemoryDocument(testFileName, `# header1`) + new InMemoryDocument(testFileName, `# header1`, 1 /* version */) ]); const provider = new MarkdownWorkspaceSymbolProvider(symbolProvider, workspaceFileProvider); @@ -60,7 +60,7 @@ suite('markdown.WorkspaceSymbolProvider', () => { assert.strictEqual((await provider.provideWorkspaceSymbols('')).length, 1); // Update file - workspaceFileProvider.updateDocument(new InMemoryDocument(testFileName, `# new header\nabc\n## header2`)); + workspaceFileProvider.updateDocument(new InMemoryDocument(testFileName, `# new header\nabc\n## header2`, 2 /* version */)); const newSymbols = await provider.provideWorkspaceSymbols(''); assert.strictEqual(newSymbols.length, 2); assert.strictEqual(newSymbols[0].name, '# new header'); diff --git a/extensions/markdown-language-features/src/typings/ref.d.ts b/extensions/markdown-language-features/src/typings/ref.d.ts index bc057c55878..954bab971e3 100644 --- a/extensions/markdown-language-features/src/typings/ref.d.ts +++ b/extensions/markdown-language-features/src/typings/ref.d.ts @@ -4,4 +4,5 @@ *--------------------------------------------------------------------------------------------*/ /// +/// /// diff --git a/extensions/markdown-language-features/src/util/arrays.ts b/extensions/markdown-language-features/src/util/arrays.ts new file mode 100644 index 00000000000..ec0ed25c55d --- /dev/null +++ b/extensions/markdown-language-features/src/util/arrays.ts @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export function equals(one: ReadonlyArray, other: ReadonlyArray, itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean { + if (one.length !== other.length) { + return false; + } + + for (let i = 0, len = one.length; i < len; i++) { + if (!itemEquals(one[i], other[i])) { + return false; + } + } + + return true; +} + +export function flatten(arr: ReadonlyArray[]): T[] { + return ([] as T[]).concat.apply([], arr); +} \ No newline at end of file diff --git a/extensions/markdown-language-features/src/util/dispose.ts b/extensions/markdown-language-features/src/util/dispose.ts index 19b3b3f4f19..548094c28e5 100644 --- a/extensions/markdown-language-features/src/util/dispose.ts +++ b/extensions/markdown-language-features/src/util/dispose.ts @@ -14,3 +14,29 @@ export function disposeAll(disposables: vscode.Disposable[]) { } } +export abstract class Disposable { + private _isDisposed = false; + + protected _disposables: vscode.Disposable[] = []; + + public dispose(): any { + if (this._isDisposed) { + return; + } + this._isDisposed = true; + disposeAll(this._disposables); + } + + protected _register(value: T): T { + if (this._isDisposed) { + value.dispose(); + } else { + this._disposables.push(value); + } + return value; + } + + protected get isDisposed() { + return this._isDisposed; + } +} \ No newline at end of file diff --git a/extensions/markdown-language-features/src/util/links.ts b/extensions/markdown-language-features/src/util/links.ts index 1afcbff83bd..c1c2b1bdfb7 100644 --- a/extensions/markdown-language-features/src/util/links.ts +++ b/extensions/markdown-language-features/src/util/links.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; -const knownSchemes = ['http:', 'https:', 'file:', 'mailto:', 'data:', 'vscode-resource:']; +const knownSchemes = ['http:', 'https:', 'file:', 'mailto:', 'data:', `${vscode.env.uriScheme}:`, 'vscode:', 'vscode-insiders:', 'vscode-resource:']; export function getUriForLinkWithKnownExternalScheme( link: string, @@ -15,4 +15,4 @@ export function getUriForLinkWithKnownExternalScheme( } return undefined; -} \ No newline at end of file +} diff --git a/extensions/markdown-language-features/src/util/resources.ts b/extensions/markdown-language-features/src/util/resources.ts new file mode 100644 index 00000000000..1def7adcce0 --- /dev/null +++ b/extensions/markdown-language-features/src/util/resources.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; + +export interface WebviewResourceProvider { + toWebviewResource(resource: vscode.Uri): vscode.Uri; + + readonly cspSource: string; +} + +export function normalizeResource( + base: vscode.Uri, + resource: vscode.Uri +): vscode.Uri { + // If we have a windows path and are loading a workspace with an authority, + // make sure we use a unc path with an explicit localhost authority. + // + // Otherwise, the `` rule will insert the authority into the resolved resource + // URI incorrectly. + if (base.authority && !resource.authority) { + const driveMatch = resource.path.match(/^\/(\w):\//); + if (driveMatch) { + return vscode.Uri.file(`\\\\localhost\\${driveMatch[1]}$\\${resource.fsPath.replace(/^\w:\\/, '')}`).with({ + fragment: resource.fragment, + query: resource.query + }); + } + } + return resource; +} \ No newline at end of file diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 071b5b8e161..a1b876e7dc8 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -29,10 +29,10 @@ resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.2.tgz#5d9ad19e6e6508cdd2f2596df86fd0aade598660" integrity sha1-XZrRnm5lCM3S8llt+G/Qqt5ZhmA= -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== abbrev@1: version "1.1.1" @@ -159,10 +159,10 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -applicationinsights@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.6.tgz#bc201810de91cea910dab34e8ad35ecde488edeb" - integrity sha512-VQT3kBpJVPw5fCO5n+WUeSx0VHjxFtD7znYbILBlVgOS9/cMDuGFmV2Br3ObzFyZUDGNbEfW36fD1y2/vAiCKw== +applicationinsights@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" + integrity sha512-KzOOGdphOS/lXWMFZe5440LUdFbrLpMvh2SaRxn7BmiI550KAoSb2gIhiq6kJZ9Ir3AxRRztjhzif+e5P5IXIg== dependencies: diagnostic-channel "0.2.0" diagnostic-channel-publishers "0.2.1" @@ -2933,10 +2933,10 @@ he@1.1.1: resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= -highlight.js@9.13.1: - version "9.13.1" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e" - integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A== +highlight.js@9.15.8: + version "9.15.8" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.8.tgz#f344fda123f36f1a65490e932cf90569e4999971" + integrity sha512-RrapkKQWwE+wKdF73VsOa2RQdIoO3mxwJ4P8mhbI6KYJUraUHRKM5w5zQQKXNk0xNL4UVRdulV9SBJcmzJNzVA== hmac-drbg@^1.0.0: version "1.0.1" @@ -3895,6 +3895,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-it-front-matter@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/markdown-it-front-matter/-/markdown-it-front-matter-0.1.2.tgz#e50bf56e77e6a4f5ac4ffa894d4d45ccd9896b20" + integrity sha1-5Qv1bnfmpPWsT/qJTU1FzNmJayA= + markdown-it@^8.4.2: version "8.4.2" resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54" @@ -6005,10 +6010,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^2.7.2: - version "2.7.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836" - integrity sha512-p5TCYZDAO0m4G344hD+wx/LATebLWZNkkh2asWUFqSsD2OrDNhbAHuSjobrmsUmdzjJjEeZVU9g1h3O6vpstnw== +typescript@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.1.tgz#6de14e1db4b8a006ac535e482c8ba018c55f750b" + integrity sha512-cTmIDFW7O0IHbn1DPYjkiebHxwtCMU+eTy30ZtJNBPF9j2O1ITu5XH2YnBeVRKWHqF+3JQwWJv0Q0aUgX8W7IA== uc.micro@^1.0.1: version "1.0.3" @@ -6308,12 +6313,12 @@ vm-browserify@0.0.4: dependencies: indexof "0.0.1" -vscode-extension-telemetry@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.0.tgz#3cdcb61d03829966bd04b5f11471a1e40d6abaad" - integrity sha512-WVCnP+uLxlqB6UD98yQNV47mR5Rf79LFxpuZhSPhEf0Sb4tPZed3a63n003/dchhOwyCTCBuNN4n8XKJkLEI1Q== +vscode-extension-telemetry@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b" + integrity sha512-TkKKG/B/J94DP5qf6xWB4YaqlhWDg6zbbqVx7Bz//stLQNnfE9XS1xm3f6fl24c5+bnEK0/wHgMgZYKIKxPeUA== dependencies: - applicationinsights "1.0.6" + applicationinsights "1.0.8" vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/merge-conflict/package.json b/extensions/merge-conflict/package.json index efc0ff0cf7a..2828669b04d 100644 --- a/extensions/merge-conflict/package.json +++ b/extensions/merge-conflict/package.json @@ -5,6 +5,7 @@ "description": "%description%", "icon": "resources/icons/merge-conflict.png", "version": "1.0.0", + "license": "MIT", "aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217", "engines": { "vscode": "^1.5.0" @@ -114,6 +115,21 @@ "type": "boolean", "description": "%config.autoNavigateNextConflictEnabled%", "default": false + }, + "merge-conflict.diffViewPosition": { + "type": "string", + "enum": [ + "Current", + "Beside", + "Below" + ], + "description": "%config.diffViewPosition%", + "enumDescriptions": [ + "%config.diffViewPosition.current%", + "%config.diffViewPosition.beside%", + "%config.diffViewPosition.below%" + ], + "default": "Current" } } } @@ -122,6 +138,6 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "8.0.33" + "@types/node": "^10.14.8" } } diff --git a/extensions/merge-conflict/package.nls.json b/extensions/merge-conflict/package.nls.json index 94599bf281e..3310dac7e21 100644 --- a/extensions/merge-conflict/package.nls.json +++ b/extensions/merge-conflict/package.nls.json @@ -15,5 +15,9 @@ "config.title": "Merge Conflict", "config.autoNavigateNextConflictEnabled": "Whether to automatically navigate to the next merge conflict after resolving a merge conflict.", "config.codeLensEnabled": "Create a Code Lens for merge conflict blocks within editor.", - "config.decoratorsEnabled": "Create decorators for merge conflict blocks within editor." + "config.decoratorsEnabled": "Create decorators for merge conflict blocks within editor.", + "config.diffViewPosition": "Controls where the diff view should be opened when comparing changes in merge conflicts.", + "config.diffViewPosition.current": "Open the diff view in the current editor group.", + "config.diffViewPosition.beside": "Open the diff view next to the current editor group.", + "config.diffViewPosition.below": "Open the diff view below the current editor group." } \ No newline at end of file diff --git a/extensions/merge-conflict/src/commandHandler.ts b/extensions/merge-conflict/src/commandHandler.ts index 3247b592f88..f79c6650af0 100644 --- a/extensions/merge-conflict/src/commandHandler.ts +++ b/extensions/merge-conflict/src/commandHandler.ts @@ -34,8 +34,8 @@ export default class CommandHandler implements vscode.Disposable { this.registerTextEditorCommand('merge-conflict.accept.incoming', this.acceptIncoming), this.registerTextEditorCommand('merge-conflict.accept.selection', this.acceptSelection), this.registerTextEditorCommand('merge-conflict.accept.both', this.acceptBoth), - this.registerTextEditorCommand('merge-conflict.accept.all-current', this.acceptAllCurrent), - this.registerTextEditorCommand('merge-conflict.accept.all-incoming', this.acceptAllIncoming), + this.registerTextEditorCommand('merge-conflict.accept.all-current', this.acceptAllCurrent, this.acceptAllCurrentResources), + this.registerTextEditorCommand('merge-conflict.accept.all-incoming', this.acceptAllIncoming, this.acceptAllIncomingResources), this.registerTextEditorCommand('merge-conflict.accept.all-both', this.acceptAllBoth), this.registerTextEditorCommand('merge-conflict.next', this.navigateNext), this.registerTextEditorCommand('merge-conflict.previous', this.navigatePrevious), @@ -43,8 +43,11 @@ export default class CommandHandler implements vscode.Disposable { ); } - private registerTextEditorCommand(command: string, cb: (editor: vscode.TextEditor, ...args: any[]) => Promise) { + private registerTextEditorCommand(command: string, cb: (editor: vscode.TextEditor, ...args: any[]) => Promise, resourceCB?: (uris: vscode.Uri[]) => Promise) { return vscode.commands.registerCommand(command, (...args) => { + if (resourceCB && args.length && args.every(arg => arg && arg.resourceUri)) { + return resourceCB.call(this, args.map(arg => arg.resourceUri)); + } const editor = vscode.window.activeTextEditor; return editor && cb.call(this, editor, ...args); }); @@ -70,6 +73,14 @@ export default class CommandHandler implements vscode.Disposable { return this.acceptAll(interfaces.CommitType.Incoming, editor); } + acceptAllCurrentResources(resources: vscode.Uri[]): Promise { + return this.acceptAllResources(interfaces.CommitType.Current, resources); + } + + acceptAllIncomingResources(resources: vscode.Uri[]): Promise { + return this.acceptAllResources(interfaces.CommitType.Incoming, resources); + } + acceptAllBoth(editor: vscode.TextEditor): Promise { return this.acceptAll(interfaces.CommitType.Both, editor); } @@ -88,18 +99,54 @@ export default class CommandHandler implements vscode.Disposable { } } + const conflicts = await this.tracker.getConflicts(editor.document); + + // Still failed to find conflict, warn the user and exit + if (!conflicts) { + vscode.window.showWarningMessage(localize('cursorNotInConflict', 'Editor cursor is not within a merge conflict')); + return; + } + const scheme = editor.document.uri.scheme; let range = conflict.current.content; + let leftRanges = conflicts.map(conflict => [conflict.current.content, conflict.range]); + let rightRanges = conflicts.map(conflict => [conflict.incoming.content, conflict.range]); + const leftUri = editor.document.uri.with({ scheme: ContentProvider.scheme, - query: JSON.stringify({ scheme, range }) + query: JSON.stringify({ scheme, range: range, ranges: leftRanges }) }); + range = conflict.incoming.content; - const rightUri = leftUri.with({ query: JSON.stringify({ scheme, range }) }); + const rightUri = leftUri.with({ query: JSON.stringify({ scheme, ranges: rightRanges }) }); + + let mergeConflictLineOffsets = 0; + for (let nextconflict of conflicts) { + if (nextconflict.range.isEqual(conflict.range)) { + break; + } else { + mergeConflictLineOffsets += (nextconflict.range.end.line - nextconflict.range.start.line) - (nextconflict.incoming.content.end.line - nextconflict.incoming.content.start.line); + } + } + const selection = new vscode.Range( + conflict.range.start.line - mergeConflictLineOffsets, conflict.range.start.character, + conflict.range.start.line - mergeConflictLineOffsets, conflict.range.start.character + ); const title = localize('compareChangesTitle', '{0}: Current Changes ⟷ Incoming Changes', fileName); - vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, title); + const mergeConflictConfig = vscode.workspace.getConfiguration('merge-conflict'); + const openToTheSide = mergeConflictConfig.get('diffViewPosition'); + const opts: vscode.TextDocumentShowOptions = { + viewColumn: openToTheSide === 'Beside' ? vscode.ViewColumn.Beside : vscode.ViewColumn.Active, + selection + }; + + if (openToTheSide === 'Below') { + await vscode.commands.executeCommand('workbench.action.newGroupBelow'); + } + + await vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, title, opts); } navigateNext(editor: vscode.TextEditor): Promise { @@ -223,10 +270,31 @@ export default class CommandHandler implements vscode.Disposable { // Apply all changes as one edit await editor.edit((edit) => conflicts.forEach(conflict => { - conflict.applyEdit(type, editor, edit); + conflict.applyEdit(type, editor.document, edit); })); } + private async acceptAllResources(type: interfaces.CommitType, resources: vscode.Uri[]): Promise { + const documents = await Promise.all(resources.map(resource => vscode.workspace.openTextDocument(resource))); + const edit = new vscode.WorkspaceEdit(); + for (const document of documents) { + const conflicts = await this.tracker.getConflicts(document); + + if (!conflicts || conflicts.length === 0) { + continue; + } + + // For get the current state of the document, as we know we are doing to do a large edit + this.tracker.forget(document); + + // Apply all changes as one edit + conflicts.forEach(conflict => { + conflict.applyEdit(type, document, { replace: (range, newText) => edit.replace(document.uri, range, newText) }); + }); + } + vscode.workspace.applyEdit(edit); + } + private async findConflictContainingSelection(editor: vscode.TextEditor, conflicts?: interfaces.IDocumentMergeConflict[]): Promise { if (!conflicts) { diff --git a/extensions/merge-conflict/src/contentProvider.ts b/extensions/merge-conflict/src/contentProvider.ts index b22ab0a21c1..d0e2b92a56c 100644 --- a/extensions/merge-conflict/src/contentProvider.ts +++ b/extensions/merge-conflict/src/contentProvider.ts @@ -23,11 +23,27 @@ export default class MergeConflictContentProvider implements vscode.TextDocument async provideTextDocumentContent(uri: vscode.Uri): Promise { try { - const { scheme, range } = JSON.parse(uri.query) as { scheme: string; range: { line: number, character: number }[] }; - const [start, end] = range; + const { scheme, ranges } = JSON.parse(uri.query) as { scheme: string, ranges: [{ line: number, character: number }[], { line: number, character: number }[]][] }; + // complete diff const document = await vscode.workspace.openTextDocument(uri.with({ scheme, query: '' })); - const text = document.getText(new vscode.Range(start.line, start.character, end.line, end.character)); + + let text = ''; + let lastPosition = new vscode.Position(0, 0); + + ranges.forEach(rangeObj => { + let [conflictRange, fullRange] = rangeObj; + const [start, end] = conflictRange; + const [fullStart, fullEnd] = fullRange; + + text += document.getText(new vscode.Range(lastPosition.line, lastPosition.character, fullStart.line, fullStart.character)); + text += document.getText(new vscode.Range(start.line, start.character, end.line, end.character)); + lastPosition = new vscode.Position(fullEnd.line, fullEnd.character); + }); + + let documentEnd = document.lineAt(document.lineCount - 1).range.end; + text += document.getText(new vscode.Range(lastPosition.line, lastPosition.character, documentEnd.line, documentEnd.character)); + return text; } catch (ex) { diff --git a/extensions/merge-conflict/src/documentMergeConflict.ts b/extensions/merge-conflict/src/documentMergeConflict.ts index 3bf94a16ea7..560c7ed8c72 100644 --- a/extensions/merge-conflict/src/documentMergeConflict.ts +++ b/extensions/merge-conflict/src/documentMergeConflict.ts @@ -25,14 +25,14 @@ export class DocumentMergeConflict implements interfaces.IDocumentMergeConflict if (edit) { - this.applyEdit(type, editor, edit); + this.applyEdit(type, editor.document, edit); return Promise.resolve(true); } - return editor.edit((edit) => this.applyEdit(type, editor, edit)); + return editor.edit((edit) => this.applyEdit(type, editor.document, edit)); } - public applyEdit(type: interfaces.CommitType, editor: vscode.TextEditor, edit: vscode.TextEditorEdit): void { + public applyEdit(type: interfaces.CommitType, document: vscode.TextDocument, edit: { replace(range: vscode.Range, newText: string): void; }): void { // Each conflict is a set of ranges as follows, note placements or newlines // which may not in in spans @@ -45,24 +45,24 @@ export class DocumentMergeConflict implements interfaces.IDocumentMergeConflict // ] if (type === interfaces.CommitType.Current) { // Replace [ Conflict Range ] with [ Current Content ] - let content = editor.document.getText(this.current.content); + let content = document.getText(this.current.content); this.replaceRangeWithContent(content, edit); } else if (type === interfaces.CommitType.Incoming) { - let content = editor.document.getText(this.incoming.content); + let content = document.getText(this.incoming.content); this.replaceRangeWithContent(content, edit); } else if (type === interfaces.CommitType.Both) { // Replace [ Conflict Range ] with [ Current Content ] + \n + [ Incoming Content ] - const currentContent = editor.document.getText(this.current.content); - const incomingContent = editor.document.getText(this.incoming.content); + const currentContent = document.getText(this.current.content); + const incomingContent = document.getText(this.incoming.content); edit.replace(this.range, currentContent.concat(incomingContent)); } } - private replaceRangeWithContent(content: string, edit: vscode.TextEditorEdit) { + private replaceRangeWithContent(content: string, edit: { replace(range: vscode.Range, newText: string): void; }) { if (this.isNewlineOnly(content)) { edit.replace(this.range, ''); return; diff --git a/extensions/merge-conflict/src/documentTracker.ts b/extensions/merge-conflict/src/documentTracker.ts index 97eeae6f87e..41be7a803e2 100644 --- a/extensions/merge-conflict/src/documentTracker.ts +++ b/extensions/merge-conflict/src/documentTracker.ts @@ -127,7 +127,7 @@ export default class DocumentMergeConflictTracker implements vscode.Disposable, } private getCacheKey(document: vscode.TextDocument): string | null { - if (document.uri && document.uri) { + if (document.uri) { return document.uri.toString(); } diff --git a/extensions/merge-conflict/src/interfaces.ts b/extensions/merge-conflict/src/interfaces.ts index bab96d13318..836bb5baa5a 100644 --- a/extensions/merge-conflict/src/interfaces.ts +++ b/extensions/merge-conflict/src/interfaces.ts @@ -25,7 +25,7 @@ export interface IExtensionConfiguration { export interface IDocumentMergeConflict extends IDocumentMergeConflictDescriptor { commitEdit(type: CommitType, editor: vscode.TextEditor, edit?: vscode.TextEditorEdit): Thenable; - applyEdit(type: CommitType, editor: vscode.TextEditor, edit: vscode.TextEditorEdit): void; + applyEdit(type: CommitType, document: vscode.TextDocument, edit: { replace(range: vscode.Range, newText: string): void; }): void; } export interface IDocumentMergeConflictDescriptor { diff --git a/extensions/merge-conflict/yarn.lock b/extensions/merge-conflict/yarn.lock index 6767cb8d8c2..e6247e29255 100644 --- a/extensions/merge-conflict/yarn.lock +++ b/extensions/merge-conflict/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@8.0.33": - version "8.0.33" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd" - integrity sha512-vmCdO8Bm1ExT+FWfC9sd9r4jwqM7o97gGy2WBshkkXbf/2nLAJQUrZfIhw27yVOtLUev6kSZc4cav/46KbDd8A== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/npm/package.json b/extensions/npm/package.json index 6c8578ad784..843255c2141 100644 --- a/extensions/npm/package.json +++ b/extensions/npm/package.json @@ -4,6 +4,7 @@ "displayName": "%displayName%", "description": "%description%", "version": "1.0.1", + "license": "MIT", "engines": { "vscode": "0.10.x" }, @@ -24,12 +25,13 @@ }, "devDependencies": { "@types/minimatch": "^3.0.3", - "@types/node": "^8.10.25" + "@types/node": "^10.14.8" }, "main": "./out/main", "activationEvents": [ "onCommand:workbench.action.tasks.runTask", "onLanguage:json", + "workspaceContains:package.json", "onView:npm" ], "contributes": { @@ -46,7 +48,7 @@ { "id": "npm", "name": "%view.name%", - "when": "config.npm.enableScriptExplorer" + "when": "npm:showScriptExplorer || config.npm.enableScriptExplorer" } ] }, diff --git a/extensions/npm/resources/dark/continue.svg b/extensions/npm/resources/dark/continue.svg index e6eb6041129..8b0a58eca9b 100644 --- a/extensions/npm/resources/dark/continue.svg +++ b/extensions/npm/resources/dark/continue.svg @@ -1 +1,3 @@ -continue \ No newline at end of file + + + diff --git a/extensions/npm/resources/dark/debug.svg b/extensions/npm/resources/dark/debug.svg index e211df43ef6..e4c1b7a927b 100644 --- a/extensions/npm/resources/dark/debug.svg +++ b/extensions/npm/resources/dark/debug.svg @@ -1,7 +1,5 @@ - - - - - - + + + + diff --git a/extensions/npm/resources/dark/prepostscript.svg b/extensions/npm/resources/dark/prepostscript.svg index cc9bcee715a..a8c87f2d8f6 100644 --- a/extensions/npm/resources/dark/prepostscript.svg +++ b/extensions/npm/resources/dark/prepostscript.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + + + diff --git a/extensions/npm/resources/dark/refresh.svg b/extensions/npm/resources/dark/refresh.svg index d79fdaa4e8e..ec0c43f0bc3 100644 --- a/extensions/npm/resources/dark/refresh.svg +++ b/extensions/npm/resources/dark/refresh.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + + diff --git a/extensions/npm/resources/dark/script.svg b/extensions/npm/resources/dark/script.svg index f90781897a7..7137a9d7bb5 100644 --- a/extensions/npm/resources/dark/script.svg +++ b/extensions/npm/resources/dark/script.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/npm/resources/light/continue.svg b/extensions/npm/resources/light/continue.svg index a4dd1cd3ca8..2563bfa114b 100644 --- a/extensions/npm/resources/light/continue.svg +++ b/extensions/npm/resources/light/continue.svg @@ -1 +1,3 @@ -continue \ No newline at end of file + + + diff --git a/extensions/npm/resources/light/debug.svg b/extensions/npm/resources/light/debug.svg index b8efb1c8f77..81a5ffb6b11 100644 --- a/extensions/npm/resources/light/debug.svg +++ b/extensions/npm/resources/light/debug.svg @@ -1,7 +1,5 @@ - - - - - - + + + + diff --git a/extensions/npm/resources/light/prepostscript.svg b/extensions/npm/resources/light/prepostscript.svg index e59d80cd323..87eb59e12a6 100644 --- a/extensions/npm/resources/light/prepostscript.svg +++ b/extensions/npm/resources/light/prepostscript.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + + + diff --git a/extensions/npm/resources/light/refresh.svg b/extensions/npm/resources/light/refresh.svg index e0345748192..a5b88123a0e 100644 --- a/extensions/npm/resources/light/refresh.svg +++ b/extensions/npm/resources/light/refresh.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + + diff --git a/extensions/npm/resources/light/script.svg b/extensions/npm/resources/light/script.svg index fb1c74cf773..60f77501db7 100644 --- a/extensions/npm/resources/light/script.svg +++ b/extensions/npm/resources/light/script.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/extensions/npm/src/features/bowerJSONContribution.ts b/extensions/npm/src/features/bowerJSONContribution.ts index 4770303760c..705e40d34e7 100644 --- a/extensions/npm/src/features/bowerJSONContribution.ts +++ b/extensions/npm/src/features/bowerJSONContribution.ts @@ -167,7 +167,7 @@ export class BowerJSONContribution implements IJSONContribution { if (url.indexOf('git://') === 0) { url = url.substring(6); } - if (url.lastIndexOf('.git') === url.length - 4) { + if (url.length >= 4 && url.substr(url.length - 4) === '.git') { url = url.substring(0, url.length - 4); } return url; diff --git a/extensions/npm/src/features/packageJSONContribution.ts b/extensions/npm/src/features/packageJSONContribution.ts index 3635171a4f1..17e194cad32 100644 --- a/extensions/npm/src/features/packageJSONContribution.ts +++ b/extensions/npm/src/features/packageJSONContribution.ts @@ -9,6 +9,7 @@ import { XHRRequest } from 'request-light'; import { Location } from 'jsonc-parser'; import { textToMarkedString } from './markedTextUtil'; +import * as cp from 'child_process'; import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); @@ -26,7 +27,7 @@ export class PackageJSONContribution implements IJSONContribution { 'shelljs', 'gulp', 'yargs', 'browserify', 'minimatch', 'react', 'less', 'prompt', 'inquirer', 'ws', 'event-stream', 'inherits', 'mysql', 'esprima', 'jsdom', 'stylus', 'when', 'readable-stream', 'aws-sdk', 'concat-stream', 'chai', 'Thenable', 'wrench']; - private knownScopes = ['@types', '@angular']; + private knownScopes = ['@types', '@angular', '@babel', '@nuxtjs', '@vue', '@bazel']; private xhr: XHRRequest; public getDocumentSelector(): DocumentSelector { @@ -73,11 +74,25 @@ export class PackageJSONContribution implements IJSONContribution { let queryUrl: string; if (currentWord.length > 0) { if (currentWord[0] === '@') { - return this.collectScopedPackages(currentWord, addValue, isLast, collector); + if (currentWord.indexOf('/') !== -1) { + return this.collectScopedPackages(currentWord, addValue, isLast, collector); + } + for (let scope of this.knownScopes) { + const proposal = new CompletionItem(scope); + proposal.kind = CompletionItemKind.Property; + proposal.insertText = new SnippetString().appendText(`"${scope}/`).appendTabstop().appendText('"'); + proposal.filterText = JSON.stringify(scope); + proposal.documentation = ''; + proposal.command = { + title: '', + command: 'editor.action.triggerSuggest' + }; + collector.add(proposal); + } + collector.setAsIncomplete(); } - queryUrl = 'https://skimdb.npmjs.com/registry/_design/app/_view/browseAll?group_level=2&limit=' + LIMIT + '&start_key=%5B%22' + encodeURIComponent(currentWord) + '%22%5D&end_key=%5B%22' + encodeURIComponent(currentWord + 'z') + '%22,%7B%7D%5D'; - + queryUrl = `https://api.npms.io/v2/search/suggestions?size=${LIMIT}&q=${encodeURIComponent(currentWord)}`; return this.xhr({ url: queryUrl, agent: USER_AGENT @@ -85,26 +100,10 @@ export class PackageJSONContribution implements IJSONContribution { if (success.status === 200) { try { const obj = JSON.parse(success.responseText); - if (obj && Array.isArray(obj.rows)) { - const results = <{ key: string[]; }[]>obj.rows; + if (obj && Array.isArray(obj)) { + const results = <{ package: SearchPackageInfo; }[]>obj; for (const result of results) { - const keys = result.key; - if (Array.isArray(keys) && keys.length > 0) { - const name = keys[0]; - const insertText = new SnippetString().appendText(JSON.stringify(name)); - if (addValue) { - insertText.appendText(': "').appendTabstop().appendText('"'); - if (!isLast) { - insertText.appendText(','); - } - } - const proposal = new CompletionItem(name); - proposal.kind = CompletionItemKind.Property; - proposal.insertText = insertText; - proposal.filterText = JSON.stringify(name); - proposal.documentation = keys[1]; - collector.add(proposal); - } + this.processPackage(result.package, addValue, isLast, collector); } if (results.length === LIMIT) { collector.setAsIncomplete(); @@ -148,22 +147,13 @@ export class PackageJSONContribution implements IJSONContribution { private collectScopedPackages(currentWord: string, addValue: boolean, isLast: boolean, collector: ISuggestionsCollector): Thenable { let segments = currentWord.split('/'); - if (segments.length === 1) { - for (let scope of this.knownScopes) { - const proposal = new CompletionItem(scope); - proposal.kind = CompletionItemKind.Property; - proposal.insertText = new SnippetString().appendText(`"${scope}/`).appendTabstop().appendText('"'); - proposal.filterText = JSON.stringify(scope); - proposal.documentation = ''; - proposal.command = { - title: '', - command: 'editor.action.triggerSuggest' - }; - collector.add(proposal); - } - } else if (segments.length === 2 && segments[0].length > 1) { + if (segments.length === 2 && segments[0].length > 1) { let scope = segments[0].substr(1); - let queryUrl = `https://registry.npmjs.org/-/v1/search?text=scope:${scope}%20${segments[1]}&size=${SCOPED_LIMIT}&popularity=1.0`; + let name = segments[1]; + if (name.length < 4) { + name = ''; + } + let queryUrl = `https://api.npms.io/v2/search?q=scope:${scope}%20${name}&size=250`; return this.xhr({ url: queryUrl, agent: USER_AGENT @@ -171,31 +161,10 @@ export class PackageJSONContribution implements IJSONContribution { if (success.status === 200) { try { const obj = JSON.parse(success.responseText); - if (obj && Array.isArray(obj.objects)) { - const objects = <{ package: { name: string; version: string, description: string; } }[]>obj.objects; + if (obj && Array.isArray(obj.results)) { + const objects = <{ package: SearchPackageInfo }[]>obj.results; for (let object of objects) { - if (object.package && object.package.name) { - const name = object.package.name; - const insertText = new SnippetString().appendText(JSON.stringify(name)); - if (addValue) { - insertText.appendText(': "'); - if (object.package.version) { - insertText.appendVariable('version', object.package.version); - } else { - insertText.appendTabstop(); - } - insertText.appendText('"'); - if (!isLast) { - insertText.appendText(','); - } - } - const proposal = new CompletionItem(name); - proposal.kind = CompletionItemKind.Property; - proposal.insertText = insertText; - proposal.filterText = JSON.stringify(name); - proposal.documentation = object.package.description || ''; - collector.add(proposal); - } + this.processPackage(object.package, addValue, isLast, collector); } if (objects.length === SCOPED_LIMIT) { collector.setAsIncomplete(); @@ -225,38 +194,29 @@ export class PackageJSONContribution implements IJSONContribution { if ((location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']) || location.matches(['optionalDependencies', '*']) || location.matches(['peerDependencies', '*']))) { const currentKey = location.path[location.path.length - 1]; if (typeof currentKey === 'string') { - const queryUrl = 'https://registry.npmjs.org/' + encodeURIComponent(currentKey).replace('%40', '@'); - return this.xhr({ - url: queryUrl, - agent: USER_AGENT - }).then((success) => { - try { - const obj = JSON.parse(success.responseText); - const latest = obj && obj['dist-tags'] && obj['dist-tags']['latest']; - if (latest) { - let name = JSON.stringify(latest); - let proposal = new CompletionItem(name); - proposal.kind = CompletionItemKind.Property; - proposal.insertText = name; - proposal.documentation = localize('json.npm.latestversion', 'The currently latest version of the package'); - result.add(proposal); + return this.npmView(currentKey).then(info => { + const latest = info.distTagsLatest; + if (latest) { + let name = JSON.stringify(latest); + let proposal = new CompletionItem(name); + proposal.kind = CompletionItemKind.Property; + proposal.insertText = name; + proposal.documentation = localize('json.npm.latestversion', 'The currently latest version of the package'); + result.add(proposal); - name = JSON.stringify('^' + latest); - proposal = new CompletionItem(name); - proposal.kind = CompletionItemKind.Property; - proposal.insertText = name; - proposal.documentation = localize('json.npm.majorversion', 'Matches the most recent major version (1.x.x)'); - result.add(proposal); + name = JSON.stringify('^' + latest); + proposal = new CompletionItem(name); + proposal.kind = CompletionItemKind.Property; + proposal.insertText = name; + proposal.documentation = localize('json.npm.majorversion', 'Matches the most recent major version (1.x.x)'); + result.add(proposal); - name = JSON.stringify('~' + latest); - proposal = new CompletionItem(name); - proposal.kind = CompletionItemKind.Property; - proposal.insertText = name; - proposal.documentation = localize('json.npm.minorversion', 'Matches the most recent minor version (1.2.x)'); - result.add(proposal); - } - } catch (e) { - // ignore + name = JSON.stringify('~' + latest); + proposal = new CompletionItem(name); + proposal.kind = CompletionItemKind.Property; + proposal.insertText = name; + proposal.documentation = localize('json.npm.minorversion', 'Matches the most recent minor version (1.2.x)'); + result.add(proposal); } return 0; }, () => { @@ -284,37 +244,38 @@ export class PackageJSONContribution implements IJSONContribution { } private getInfo(pack: string): Thenable { - - const queryUrl = 'https://registry.npmjs.org/' + encodeURIComponent(pack).replace('%40', '@'); - return this.xhr({ - url: queryUrl, - agent: USER_AGENT - }).then((success) => { - try { - const obj = JSON.parse(success.responseText); - if (obj) { - const result: string[] = []; - if (obj.description) { - result.push(obj.description); - } - const latest = obj && obj['dist-tags'] && obj['dist-tags']['latest']; - if (latest) { - result.push(localize('json.npm.version.hover', 'Latest version: {0}', latest)); - } - if (obj.homepage) { - result.push(obj.homepage); - } - return result; - } - } catch (e) { - // ignore - } - return []; + return this.npmView(pack).then(info => { + const result: string[] = []; + result.push(info.description || ''); + result.push(info.distTagsLatest ? localize('json.npm.version.hover', 'Latest version: {0}', info.distTagsLatest) : ''); + result.push(info.homepage || ''); + return result; }, () => { return []; }); } + private npmView(pack: string): Promise { + return new Promise((resolve, reject) => { + const command = 'npm view --json ' + pack + ' description dist-tags.latest homepage'; + cp.exec(command, (error, stdout) => { + if (error) { + return reject(); + } + try { + const content = JSON.parse(stdout); + resolve({ + description: content['description'], + distTagsLatest: content['dist-tags.latest'], + homepage: content['homepage'] + }); + } catch (e) { + reject(); + } + }); + }); + } + public getInfoContribution(_fileName: string, location: Location): Thenable | null { if ((location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']) || location.matches(['optionalDependencies', '*']) || location.matches(['peerDependencies', '*']))) { const pack = location.path[location.path.length - 1]; @@ -329,4 +290,41 @@ export class PackageJSONContribution implements IJSONContribution { } return null; } + + private processPackage(pack: SearchPackageInfo, addValue: boolean, isLast: boolean, collector: ISuggestionsCollector) { + if (pack && pack.name) { + const name = pack.name; + const insertText = new SnippetString().appendText(JSON.stringify(name)); + if (addValue) { + insertText.appendText(': "'); + if (pack.version) { + insertText.appendVariable('version', pack.version); + } else { + insertText.appendTabstop(); + } + insertText.appendText('"'); + if (!isLast) { + insertText.appendText(','); + } + } + const proposal = new CompletionItem(name); + proposal.kind = CompletionItemKind.Property; + proposal.insertText = insertText; + proposal.filterText = JSON.stringify(name); + proposal.documentation = pack.description || ''; + collector.add(proposal); + } + } } + +interface SearchPackageInfo { + name: string; + description?: string; + version?: string; +} + +interface ViewPackageInfo { + description: string; + distTagsLatest?: string; + homepage?: string; +} \ No newline at end of file diff --git a/extensions/npm/src/main.ts b/extensions/npm/src/main.ts index 640c349334a..d32d245b0ed 100644 --- a/extensions/npm/src/main.ts +++ b/extensions/npm/src/main.ts @@ -7,7 +7,7 @@ import * as httpRequest from 'request-light'; import * as vscode from 'vscode'; import { addJSONProviders } from './features/jsonContributions'; import { NpmScriptsTreeDataProvider } from './npmView'; -import { invalidateTasksCache, NpmTaskProvider } from './tasks'; +import { invalidateTasksCache, NpmTaskProvider, hasPackageJson } from './tasks'; import { invalidateHoverScriptsCache, NpmScriptHoverProvider } from './scriptHover'; import { runSelectedScript } from './commands'; @@ -41,6 +41,10 @@ export async function activate(context: vscode.ExtensionContext): Promise context.subscriptions.push(d); context.subscriptions.push(vscode.commands.registerCommand('npm.runSelectedScript', runSelectedScript)); context.subscriptions.push(addJSONProviders(httpRequest.xhr)); + + if (await hasPackageJson()) { + vscode.commands.executeCommand('setContext', 'npm:showScriptExplorer', true); + } } function registerTaskProvider(context: vscode.ExtensionContext): vscode.Disposable | undefined { diff --git a/extensions/npm/src/tasks.ts b/extensions/npm/src/tasks.ts index bfe9d8cd698..0e6a28bfc33 100644 --- a/extensions/npm/src/tasks.ts +++ b/extensions/npm/src/tasks.ts @@ -5,7 +5,7 @@ import { TaskDefinition, Task, TaskGroup, WorkspaceFolder, RelativePattern, ShellExecution, Uri, workspace, - DebugConfiguration, debug, TaskProvider, TextDocument, tasks + DebugConfiguration, debug, TaskProvider, TextDocument, tasks, TaskScope } from 'vscode'; import * as path from 'path'; import * as fs from 'fs'; @@ -34,6 +34,21 @@ export class NpmTaskProvider implements TaskProvider { } public resolveTask(_task: Task): Task | undefined { + const npmTask = (_task.definition).script; + if (npmTask) { + const kind: NpmTaskDefinition = (_task.definition); + let packageJsonUri: Uri; + if (_task.scope === undefined || _task.scope === TaskScope.Global || _task.scope === TaskScope.Workspace) { + // scope is required to be a WorkspaceFolder for resolveTask + return undefined; + } + if (kind.path) { + packageJsonUri = _task.scope.uri.with({ path: _task.scope.uri.path + '/' + kind.path + 'package.json' }); + } else { + packageJsonUri = _task.scope.uri.with({ path: _task.scope.uri.path + '/package.json' }); + } + return createTask(kind, `run ${kind.script}`, _task.scope, packageJsonUri); + } return undefined; } } @@ -221,7 +236,13 @@ export function getTaskName(script: string, relativePath: string | undefined) { return script; } -export function createTask(script: string, cmd: string, folder: WorkspaceFolder, packageJsonUri: Uri, matcher?: any): Task { +export function createTask(script: NpmTaskDefinition | string, cmd: string, folder: WorkspaceFolder, packageJsonUri: Uri, matcher?: any): Task { + let kind: NpmTaskDefinition; + if (typeof script === 'string') { + kind = { type: 'npm', script: script }; + } else { + kind = script; + } function getCommandLine(folder: WorkspaceFolder, cmd: string): string { let packageManager = getPackageManager(folder); @@ -237,15 +258,11 @@ export function createTask(script: string, cmd: string, folder: WorkspaceFolder, return absolutePath.substring(rootUri.path.length + 1); } - let kind: NpmTaskDefinition = { - type: 'npm', - script: script - }; let relativePackageJson = getRelativePath(folder, packageJsonUri); if (relativePackageJson.length) { kind.path = getRelativePath(folder, packageJsonUri); } - let taskName = getTaskName(script, relativePackageJson); + let taskName = getTaskName(kind.script, relativePackageJson); let cwd = path.dirname(packageJsonUri.fsPath); return new Task(kind, folder, taskName, 'npm', new ShellExecution(getCommandLine(folder, cmd), { cwd: cwd }), matcher); } @@ -262,6 +279,22 @@ export function getPackageJsonUriFromTask(task: Task): Uri | null { return null; } +export async function hasPackageJson(): Promise { + let folders = workspace.workspaceFolders; + if (!folders) { + return false; + } + for (const folder of folders) { + if (folder.uri.scheme === 'file') { + let packageJson = path.join(folder.uri.fsPath, 'package.json'); + if (await exists(packageJson)) { + return true; + } + } + } + return false; +} + async function exists(file: string): Promise { return new Promise((resolve, _reject) => { fs.exists(file, (value) => { diff --git a/extensions/npm/yarn.lock b/extensions/npm/yarn.lock index 3851d9a4b67..e80a4ca5a2d 100644 --- a/extensions/npm/yarn.lock +++ b/extensions/npm/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== agent-base@4, agent-base@^4.1.0: version "4.2.0" diff --git a/extensions/objective-c/build/update-grammars.js b/extensions/objective-c/build/update-grammars.js new file mode 100644 index 00000000000..5518bbcb033 --- /dev/null +++ b/extensions/objective-c/build/update-grammars.js @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +var updateGrammar = require('../../../build/npm/update-grammar'); + +updateGrammar.update('jeff-hykin/cpp-textmate-grammar', '/syntaxes/objc.tmLanguage.json', './syntaxes/objective-c.tmLanguage.json', undefined, 'master', 'source/languages/cpp'); +updateGrammar.update('jeff-hykin/cpp-textmate-grammar', '/syntaxes/objcpp.tmLanguage.json', './syntaxes/objective-c++.tmLanguage.json', undefined, 'master', 'source/languages/cpp'); + diff --git a/extensions/objective-c/cgmanifest.json b/extensions/objective-c/cgmanifest.json index 1b54a305d12..f33f55aad69 100644 --- a/extensions/objective-c/cgmanifest.json +++ b/extensions/objective-c/cgmanifest.json @@ -4,14 +4,14 @@ "component": { "type": "git", "git": { - "name": "atom/language-objective-c", - "repositoryUrl": "https://github.com/atom/language-objective-c", - "commitHash": "7fdf0c40ec1d592a902ed6a7cf5565bdf12e2ae8" + "name": "jeff-hykin/cpp-textmate-grammar", + "repositoryUrl": "https://github.com/jeff-hykin/cpp-textmate-grammar", + "commitHash": "9c4f4b3291538d9f5144f02d3b6af877b84f2cb2" } }, "license": "MIT", - "description": "The files syntaxes/objective-c.tmLanguage.json and syntaxes/objective-c++.tmLanguage.json were derived from the Atom package https://github.com/atom/language-objective-c which was originally converted from the TextMate bundle https://github.com/textmate/objective-c.tmbundle.", - "version": "0.15.0" + "version": "1.12.11", + "description": "The files syntaxes/objective-c.tmLanguage.json and syntaxes/objective-c++.tmLanguage.json were derived from the language package https://github.com/jeff-hykin/cpp-textmate-grammar." } ], "version": 1 diff --git a/extensions/objective-c/package.json b/extensions/objective-c/package.json index 944b68e0538..657273ad283 100644 --- a/extensions/objective-c/package.json +++ b/extensions/objective-c/package.json @@ -4,11 +4,12 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { - "update-grammar": "node ../../build/npm/update-grammar.js atom/language-objective-c grammars/objective-c.cson ./syntaxes/objective-c.tmLanguage.json && node ../../build/npm/update-grammar.js atom/language-objective-c grammars/objective-c%2B%2B.cson ./syntaxes/objective-c++.tmLanguage.json" + "update-grammar": "node ./build/update-grammars.js" }, "contributes": { "languages": [ diff --git a/extensions/objective-c/syntaxes/objective-c++.tmLanguage.json b/extensions/objective-c/syntaxes/objective-c++.tmLanguage.json index bd24c9f0ddf..d9d1cfa5584 100644 --- a/extensions/objective-c/syntaxes/objective-c++.tmLanguage.json +++ b/extensions/objective-c/syntaxes/objective-c++.tmLanguage.json @@ -1,18 +1,7098 @@ { "information_for_contributors": [ - "This file has been converted from https://github.com/atom/language-objective-c/blob/master/grammars/objective-c%2B%2B.cson", + "This file has been converted from https://github.com/jeff-hykin/cpp-textmate-grammar/blob/master//syntaxes/objcpp.tmLanguage.json", "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/atom/language-objective-c/commit/7fdf0c40ec1d592a902ed6a7cf5565bdf12e2ae8", + "version": "https://github.com/jeff-hykin/cpp-textmate-grammar/commit/9c4f4b3291538d9f5144f02d3b6af877b84f2cb2", "name": "Objective-C++", "scopeName": "source.objcpp", "patterns": [ { - "include": "source.cpp" + "include": "#cpp_lang" }, { - "include": "source.objc" + "begin": "((@)(interface|protocol))(?!.+;)\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*((:)(?:\\s*)([A-Za-z][A-Za-z0-9]*))?(\\s|\\n)?", + "captures": { + "1": { + "name": "storage.type.objcpp" + }, + "2": { + "name": "punctuation.definition.storage.type.objcpp" + }, + "4": { + "name": "entity.name.type.objcpp" + }, + "6": { + "name": "punctuation.definition.entity.other.inherited-class.objcpp" + }, + "7": { + "name": "entity.other.inherited-class.objcpp" + }, + "8": { + "name": "meta.divider.objcpp" + }, + "9": { + "name": "meta.inherited-class.objcpp" + } + }, + "contentName": "meta.scope.interface.objcpp", + "end": "((@)end)\\b", + "name": "meta.interface-or-protocol.objcpp", + "patterns": [ + { + "include": "#interface_innards" + } + ] + }, + { + "begin": "((@)(implementation))\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*(?::\\s*([A-Za-z][A-Za-z0-9]*))?", + "captures": { + "1": { + "name": "storage.type.objcpp" + }, + "2": { + "name": "punctuation.definition.storage.type.objcpp" + }, + "4": { + "name": "entity.name.type.objcpp" + }, + "5": { + "name": "entity.other.inherited-class.objcpp" + } + }, + "contentName": "meta.scope.implementation.objcpp", + "end": "((@)end)\\b", + "name": "meta.implementation.objcpp", + "patterns": [ + { + "include": "#implementation_innards" + } + ] + }, + { + "begin": "@\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.objcpp" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objcpp" + } + }, + "name": "string.quoted.double.objcpp", + "patterns": [ + { + "include": "#string_escaped_char" + }, + { + "match": "(?x)%\n\t\t\t\t\t\t(\\d+\\$)? # field (argument #)\n\t\t\t\t\t\t[#0\\- +']* # flags\n\t\t\t\t\t\t((-?\\d+)|\\*(-?\\d+\\$)?)? # minimum field width\n\t\t\t\t\t\t(\\.((-?\\d+)|\\*(-?\\d+\\$)?)?)? # precision\n\t\t\t\t\t\t[@] # conversion type\n\t\t\t\t\t", + "name": "constant.other.placeholder.objcpp" + }, + { + "include": "#string_placeholder" + } + ] + }, + { + "begin": "\\b(id)\\s*(?=<)", + "beginCaptures": { + "1": { + "name": "storage.type.objcpp" + } + }, + "end": "(?<=>)", + "name": "meta.id-with-protocol.objcpp", + "patterns": [ + { + "include": "#protocol_list" + } + ] + }, + { + "match": "\\b(NS_DURING|NS_HANDLER|NS_ENDHANDLER)\\b", + "name": "keyword.control.macro.objcpp" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.keyword.objcpp" + } + }, + "match": "(@)(try|catch|finally|throw)\\b", + "name": "keyword.control.exception.objcpp" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.keyword.objcpp" + } + }, + "match": "(@)(synchronized)\\b", + "name": "keyword.control.synchronize.objcpp" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.keyword.objcpp" + } + }, + "match": "(@)(required|optional)\\b", + "name": "keyword.control.protocol-specification.objcpp" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.keyword.objcpp" + } + }, + "match": "(@)(defs|encode)\\b", + "name": "keyword.other.objcpp" + }, + { + "match": "\\bid\\b", + "name": "storage.type.id.objcpp" + }, + { + "match": "\\b(IBOutlet|IBAction|BOOL|SEL|id|unichar|IMP|Class|instancetype)\\b", + "name": "storage.type.objcpp" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.storage.type.objcpp" + } + }, + "match": "(@)(class|protocol)\\b", + "name": "storage.type.objcpp" + }, + { + "begin": "((@)selector)\\s*(\\()", + "beginCaptures": { + "1": { + "name": "storage.type.objcpp" + }, + "2": { + "name": "punctuation.definition.storage.type.objcpp" + }, + "3": { + "name": "punctuation.definition.storage.type.objcpp" + } + }, + "contentName": "meta.selector.method-name.objcpp", + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.storage.type.objcpp" + } + }, + "name": "meta.selector.objcpp", + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.separator.arguments.objcpp" + } + }, + "match": "\\b(?:[a-zA-Z_:][\\w]*)+", + "name": "support.function.any-method.name-of-parameter.objcpp" + } + ] + }, + { + "captures": { + "1": { + "name": "punctuation.definition.storage.modifier.objcpp" + } + }, + "match": "(@)(synchronized|public|package|private|protected)\\b", + "name": "storage.modifier.objcpp" + }, + { + "match": "\\b(YES|NO|Nil|nil)\\b", + "name": "constant.language.objcpp" + }, + { + "match": "\\bNSApp\\b", + "name": "support.variable.foundation.objcpp" + }, + { + "captures": { + "1": { + "name": "punctuation.whitespace.support.function.cocoa.leopard.objcpp" + }, + "2": { + "name": "support.function.cocoa.leopard.objcpp" + } + }, + "match": "(\\s*)\\b(NS(Rect(ToCGRect|FromCGRect)|MakeCollectable|S(tringFromProtocol|ize(ToCGSize|FromCGSize))|Draw(NinePartImage|ThreePartImage)|P(oint(ToCGPoint|FromCGPoint)|rotocolFromString)|EventMaskFromType|Value))\\b" + }, + { + "captures": { + "1": { + "name": "punctuation.whitespace.support.function.leading.cocoa.objcpp" + }, + "2": { + "name": "support.function.cocoa.objcpp" + } + }, + "match": "(\\s*)\\b(NS(R(ound(DownToMultipleOfPageSize|UpToMultipleOfPageSize)|un(CriticalAlertPanel(RelativeToWindow)?|InformationalAlertPanel(RelativeToWindow)?|AlertPanel(RelativeToWindow)?)|e(set(MapTable|HashTable)|c(ycleZone|t(Clip(List)?|F(ill(UsingOperation|List(UsingOperation|With(Grays|Colors(UsingOperation)?))?)?|romString))|ordAllocationEvent)|turnAddress|leaseAlertPanel|a(dPixel|l(MemoryAvailable|locateCollectable))|gisterServicesProvider)|angeFromString)|Get(SizeAndAlignment|CriticalAlertPanel|InformationalAlertPanel|UncaughtExceptionHandler|FileType(s)?|WindowServerMemory|AlertPanel)|M(i(n(X|Y)|d(X|Y))|ouseInRect|a(p(Remove|Get|Member|Insert(IfAbsent|KnownAbsent)?)|ke(R(ect|ange)|Size|Point)|x(Range|X|Y)))|B(itsPer(SampleFromDepth|PixelFromDepth)|e(stDepth|ep|gin(CriticalAlertSheet|InformationalAlertSheet|AlertSheet)))|S(ho(uldRetainWithZone|w(sServicesMenuItem|AnimationEffect))|tringFrom(R(ect|ange)|MapTable|S(ize|elector)|HashTable|Class|Point)|izeFromString|e(t(ShowsServicesMenuItem|ZoneName|UncaughtExceptionHandler|FocusRingStyle)|lectorFromString|archPathForDirectoriesInDomains)|wap(Big(ShortToHost|IntToHost|DoubleToHost|FloatToHost|Long(ToHost|LongToHost))|Short|Host(ShortTo(Big|Little)|IntTo(Big|Little)|DoubleTo(Big|Little)|FloatTo(Big|Little)|Long(To(Big|Little)|LongTo(Big|Little)))|Int|Double|Float|L(ittle(ShortToHost|IntToHost|DoubleToHost|FloatToHost|Long(ToHost|LongToHost))|ong(Long)?)))|H(ighlightRect|o(stByteOrder|meDirectory(ForUser)?)|eight|ash(Remove|Get|Insert(IfAbsent|KnownAbsent)?)|FSType(CodeFromFileType|OfFile))|N(umberOfColorComponents|ext(MapEnumeratorPair|HashEnumeratorItem))|C(o(n(tainsRect|vert(GlyphsToPackedGlyphs|Swapped(DoubleToHost|FloatToHost)|Host(DoubleToSwapped|FloatToSwapped)))|unt(MapTable|HashTable|Frames|Windows(ForContext)?)|py(M(emoryPages|apTableWithZone)|Bits|HashTableWithZone|Object)|lorSpaceFromDepth|mpare(MapTables|HashTables))|lassFromString|reate(MapTable(WithZone)?|HashTable(WithZone)?|Zone|File(namePboardType|ContentsPboardType)))|TemporaryDirectory|I(s(ControllerMarker|EmptyRect|FreedObject)|n(setRect|crementExtraRefCount|te(r(sect(sRect|ionR(ect|ange))|faceStyleForKey)|gralRect)))|Zone(Realloc|Malloc|Name|Calloc|Fr(omPointer|ee))|O(penStepRootDirectory|ffsetRect)|D(i(sableScreenUpdates|videRect)|ottedFrameRect|e(c(imal(Round|Multiply|S(tring|ubtract)|Normalize|Co(py|mpa(ct|re))|IsNotANumber|Divide|Power|Add)|rementExtraRefCountWasZero)|faultMallocZone|allocate(MemoryPages|Object))|raw(Gr(oove|ayBezel)|B(itmap|utton)|ColorTiledRects|TiledRects|DarkBezel|W(hiteBezel|indowBackground)|LightBezel))|U(serName|n(ionR(ect|ange)|registerServicesProvider)|pdateDynamicServices)|Java(Bundle(Setup|Cleanup)|Setup(VirtualMachine)?|Needs(ToLoadClasses|VirtualMachine)|ClassesF(orBundle|romPath)|ObjectNamedInPath|ProvidesClasses)|P(oint(InRect|FromString)|erformService|lanarFromDepth|ageSize)|E(n(d(MapTableEnumeration|HashTableEnumeration)|umerate(MapTable|HashTable)|ableScreenUpdates)|qual(R(ects|anges)|Sizes|Points)|raseRect|xtraRefCount)|F(ileTypeForHFSTypeCode|ullUserName|r(ee(MapTable|HashTable)|ame(Rect(WithWidth(UsingOperation)?)?|Address)))|Wi(ndowList(ForContext)?|dth)|Lo(cationInRange|g(v|PageSize)?)|A(ccessibility(R(oleDescription(ForUIElement)?|aiseBadArgumentException)|Unignored(Children(ForOnlyChild)?|Descendant|Ancestor)|PostNotification|ActionDescription)|pplication(Main|Load)|vailableWindowDepths|ll(MapTable(Values|Keys)|HashTableObjects|ocate(MemoryPages|Collectable|Object)))))\\b" + }, + { + "match": "\\bNS(RuleEditor|G(arbageCollector|radient)|MapTable|HashTable|Co(ndition|llectionView(Item)?)|T(oolbarItemGroup|extInputClient|r(eeNode|ackingArea))|InvocationOperation|Operation(Queue)?|D(ictionaryController|ockTile)|P(ointer(Functions|Array)|athC(o(ntrol(Delegate)?|mponentCell)|ell(Delegate)?)|r(intPanelAccessorizing|edicateEditor(RowTemplate)?))|ViewController|FastEnumeration|Animat(ionContext|ablePropertyContainer))\\b", + "name": "support.class.cocoa.leopard.objcpp" + }, + { + "match": "\\bNS(R(u(nLoop|ler(Marker|View))|e(sponder|cursiveLock|lativeSpecifier)|an(domSpecifier|geSpecifier))|G(etCommand|lyph(Generator|Storage|Info)|raphicsContext)|XML(Node|D(ocument|TD(Node)?)|Parser|Element)|M(iddleSpecifier|ov(ie(View)?|eCommand)|utable(S(tring|et)|C(haracterSet|opying)|IndexSet|D(ictionary|ata)|URLRequest|ParagraphStyle|A(ttributedString|rray))|e(ssagePort(NameServer)?|nu(Item(Cell)?|View)?|t(hodSignature|adata(Item|Query(ResultGroup|AttributeValueTuple)?)))|a(ch(BootstrapServer|Port)|trix))|B(itmapImageRep|ox|u(ndle|tton(Cell)?)|ezierPath|rowser(Cell)?)|S(hadow|c(anner|r(ipt(SuiteRegistry|C(o(ercionHandler|mmand(Description)?)|lassDescription)|ObjectSpecifier|ExecutionContext|WhoseTest)|oll(er|View)|een))|t(epper(Cell)?|atus(Bar|Item)|r(ing|eam))|imple(HorizontalTypesetter|CString)|o(cketPort(NameServer)?|und|rtDescriptor)|p(e(cifierTest|ech(Recognizer|Synthesizer)|ll(Server|Checker))|litView)|e(cureTextField(Cell)?|t(Command)?|archField(Cell)?|rializer|gmentedC(ontrol|ell))|lider(Cell)?|avePanel)|H(ost|TTP(Cookie(Storage)?|URLResponse)|elpManager)|N(ib(Con(nector|trolConnector)|OutletConnector)?|otification(Center|Queue)?|u(ll|mber(Formatter)?)|etService(Browser)?|ameSpecifier)|C(ha(ngeSpelling|racterSet)|o(n(stantString|nection|trol(ler)?|ditionLock)|d(ing|er)|unt(Command|edSet)|pying|lor(Space|P(ick(ing(Custom|Default)|er)|anel)|Well|List)?|m(p(oundPredicate|arisonPredicate)|boBox(Cell)?))|u(stomImageRep|rsor)|IImageRep|ell|l(ipView|o(seCommand|neCommand)|assDescription)|a(ched(ImageRep|URLResponse)|lendar(Date)?)|reateCommand)|T(hread|ypesetter|ime(Zone|r)|o(olbar(Item(Validations)?)?|kenField(Cell)?)|ext(Block|Storage|Container|Tab(le(Block)?)?|Input|View|Field(Cell)?|List|Attachment(Cell)?)?|a(sk|b(le(Header(Cell|View)|Column|View)|View(Item)?))|reeController)|I(n(dex(S(pecifier|et)|Path)|put(Manager|S(tream|erv(iceProvider|er(MouseTracker)?)))|vocation)|gnoreMisspelledWords|mage(Rep|Cell|View)?)|O(ut(putStream|lineView)|pen(GL(Context|Pixel(Buffer|Format)|View)|Panel)|bj(CTypeSerializationCallBack|ect(Controller)?))|D(i(st(antObject(Request)?|ributed(NotificationCenter|Lock))|ctionary|rectoryEnumerator)|ocument(Controller)?|e(serializer|cimalNumber(Behaviors|Handler)?|leteCommand)|at(e(Components|Picker(Cell)?|Formatter)?|a)|ra(wer|ggingInfo))|U(ser(InterfaceValidations|Defaults(Controller)?)|RL(Re(sponse|quest)|Handle(Client)?|C(onnection|ache|redential(Storage)?)|Download(Delegate)?|Prot(ocol(Client)?|ectionSpace)|AuthenticationChallenge(Sender)?)?|n(iqueIDSpecifier|doManager|archiver))|P(ipe|o(sitionalSpecifier|pUpButton(Cell)?|rt(Message|NameServer|Coder)?)|ICTImageRep|ersistentDocument|DFImageRep|a(steboard|nel|ragraphStyle|geLayout)|r(int(Info|er|Operation|Panel)|o(cessInfo|tocolChecker|perty(Specifier|ListSerialization)|gressIndicator|xy)|edicate))|E(numerator|vent|PSImageRep|rror|x(ception|istsCommand|pression))|V(iew(Animation)?|al(idated(ToobarItem|UserInterfaceItem)|ue(Transformer)?))|Keyed(Unarchiver|Archiver)|Qui(ckDrawView|tCommand)|F(ile(Manager|Handle|Wrapper)|o(nt(Manager|Descriptor|Panel)?|rm(Cell|atter)))|W(hoseSpecifier|indow(Controller)?|orkspace)|L(o(c(k(ing)?|ale)|gicalTest)|evelIndicator(Cell)?|ayoutManager)|A(ssertionHandler|nimation|ctionCell|ttributedString|utoreleasePool|TSTypesetter|ppl(ication|e(Script|Event(Manager|Descriptor)))|ffineTransform|lert|r(chiver|ray(Controller)?)))\\b", + "name": "support.class.cocoa.objcpp" + }, + { + "match": "\\bNS(R(oundingMode|ule(Editor(RowType|NestingMode)|rOrientation)|e(questUserAttentionType|lativePosition))|G(lyphInscription|radientDrawingOptions)|XML(NodeKind|D(ocumentContentKind|TDNodeKind)|ParserError)|M(ultibyteGlyphPacking|apTableOptions)|B(itmapFormat|oxType|ezierPathElement|ackgroundStyle|rowserDropOperation)|S(tr(ing(CompareOptions|DrawingOptions|EncodingConversionOptions)|eam(Status|Event))|p(eechBoundary|litViewDividerStyle)|e(archPathD(irectory|omainMask)|gmentS(tyle|witchTracking))|liderType|aveOptions)|H(TTPCookieAcceptPolicy|ashTableOptions)|N(otification(SuspensionBehavior|Coalescing)|umberFormatter(RoundingMode|Behavior|Style|PadPosition)|etService(sError|Options))|C(haracterCollection|o(lor(RenderingIntent|SpaceModel|PanelMode)|mp(oundPredicateType|arisonPredicateModifier))|ellStateValue|al(culationError|endarUnit))|T(ypesetterControlCharacterAction|imeZoneNameStyle|e(stComparisonOperation|xt(Block(Dimension|V(erticalAlignment|alueType)|Layer)|TableLayoutAlgorithm|FieldBezelStyle))|ableView(SelectionHighlightStyle|ColumnAutoresizingStyle)|rackingAreaOptions)|I(n(sertionPosition|te(rfaceStyle|ger))|mage(RepLoadStatus|Scaling|CacheMode|FrameStyle|LoadStatus|Alignment))|Ope(nGLPixelFormatAttribute|rationQueuePriority)|Date(Picker(Mode|Style)|Formatter(Behavior|Style))|U(RL(RequestCachePolicy|HandleStatus|C(acheStoragePolicy|redentialPersistence))|Integer)|P(o(stingStyle|int(ingDeviceType|erFunctionsOptions)|pUpArrowPosition)|athStyle|r(int(ing(Orientation|PaginationMode)|erTableStatus|PanelOptions)|opertyList(MutabilityOptions|Format)|edicateOperatorType))|ExpressionType|KeyValue(SetMutationKind|Change)|QTMovieLoopMode|F(indPanel(SubstringMatchType|Action)|o(nt(RenderingMode|FamilyClass)|cusRingPlacement))|W(hoseSubelementIdentifier|ind(ingRule|ow(B(utton|ackingLocation)|SharingType|CollectionBehavior)))|L(ine(MovementDirection|SweepDirection|CapStyle|JoinStyle)|evelIndicatorStyle)|Animation(BlockingMode|Curve))\\b", + "name": "support.type.cocoa.leopard.objcpp" + }, + { + "match": "\\bC(I(Sampler|Co(ntext|lor)|Image(Accumulator)?|PlugIn(Registration)?|Vector|Kernel|Filter(Generator|Shape)?)|A(Renderer|MediaTiming(Function)?|BasicAnimation|ScrollLayer|Constraint(LayoutManager)?|T(iledLayer|extLayer|rans(ition|action))|OpenGLLayer|PropertyAnimation|KeyframeAnimation|Layer|A(nimation(Group)?|ction)))\\b", + "name": "support.class.quartz.objcpp" + }, + { + "match": "\\bC(G(Float|Point|Size|Rect)|IFormat|AConstraintAttribute)\\b", + "name": "support.type.quartz.objcpp" + }, + { + "match": "\\bNS(R(ect(Edge)?|ange)|G(lyph(Relation|LayoutMode)?|radientType)|M(odalSession|a(trixMode|p(Table|Enumerator)))|B(itmapImageFileType|orderType|uttonType|ezelStyle|ackingStoreType|rowserColumnResizingType)|S(cr(oll(er(Part|Arrow)|ArrowPosition)|eenAuxiliaryOpaque)|tringEncoding|ize|ocketNativeHandle|election(Granularity|Direction|Affinity)|wapped(Double|Float)|aveOperationType)|Ha(sh(Table|Enumerator)|ndler(2)?)|C(o(ntrol(Size|Tint)|mp(ositingOperation|arisonResult))|ell(State|Type|ImagePosition|Attribute))|T(hreadPrivate|ypesetterGlyphInfo|i(ckMarkPosition|tlePosition|meInterval)|o(ol(TipTag|bar(SizeMode|DisplayMode))|kenStyle)|IFFCompression|ext(TabType|Alignment)|ab(State|leViewDropOperation|ViewType)|rackingRectTag)|ImageInterpolation|Zone|OpenGL(ContextAuxiliary|PixelFormatAuxiliary)|D(ocumentChangeType|atePickerElementFlags|ra(werState|gOperation))|UsableScrollerParts|P(oint|r(intingPageOrder|ogressIndicator(Style|Th(ickness|readInfo))))|EventType|KeyValueObservingOptions|Fo(nt(SymbolicTraits|TraitMask|Action)|cusRingType)|W(indow(OrderingMode|Depth)|orkspace(IconCreationOptions|LaunchOptions)|ritingDirection)|L(ineBreakMode|ayout(Status|Direction))|A(nimation(Progress|Effect)|ppl(ication(TerminateReply|DelegateReply|PrintReply)|eEventManagerSuspensionID)|ffineTransformStruct|lertStyle))\\b", + "name": "support.type.cocoa.objcpp" + }, + { + "match": "\\bNS(NotFound|Ordered(Ascending|Descending|Same))\\b", + "name": "support.constant.cocoa.objcpp" + }, + { + "match": "\\bNS(MenuDidBeginTracking|ViewDidUpdateTrackingAreas)?Notification\\b", + "name": "support.constant.notification.cocoa.leopard.objcpp" + }, + { + "match": "\\bNS(Menu(Did(RemoveItem|SendAction|ChangeItem|EndTracking|AddItem)|WillSendAction)|S(ystemColorsDidChange|plitView(DidResizeSubviews|WillResizeSubviews))|C(o(nt(extHelpModeDid(Deactivate|Activate)|rolT(intDidChange|extDid(BeginEditing|Change|EndEditing)))|lor(PanelColorDidChange|ListDidChange)|mboBox(Selection(IsChanging|DidChange)|Will(Dismiss|PopUp)))|lassDescriptionNeededForClass)|T(oolbar(DidRemoveItem|WillAddItem)|ext(Storage(DidProcessEditing|WillProcessEditing)|Did(BeginEditing|Change|EndEditing)|View(DidChange(Selection|TypingAttributes)|WillChangeNotifyingTextView))|ableView(Selection(IsChanging|DidChange)|ColumnDid(Resize|Move)))|ImageRepRegistryDidChange|OutlineView(Selection(IsChanging|DidChange)|ColumnDid(Resize|Move)|Item(Did(Collapse|Expand)|Will(Collapse|Expand)))|Drawer(Did(Close|Open)|Will(Close|Open))|PopUpButton(CellWillPopUp|WillPopUp)|View(GlobalFrameDidChange|BoundsDidChange|F(ocusDidChange|rameDidChange))|FontSetChanged|W(indow(Did(Resi(ze|gn(Main|Key))|M(iniaturize|ove)|Become(Main|Key)|ChangeScreen(|Profile)|Deminiaturize|Update|E(ndSheet|xpose))|Will(M(iniaturize|ove)|BeginSheet|Close))|orkspace(SessionDid(ResignActive|BecomeActive)|Did(Mount|TerminateApplication|Unmount|PerformFileOperation|Wake|LaunchApplication)|Will(Sleep|Unmount|PowerOff|LaunchApplication)))|A(ntialiasThresholdChanged|ppl(ication(Did(ResignActive|BecomeActive|Hide|ChangeScreenParameters|U(nhide|pdate)|FinishLaunching)|Will(ResignActive|BecomeActive|Hide|Terminate|U(nhide|pdate)|FinishLaunching))|eEventManagerWillProcessFirstEvent)))Notification\\b", + "name": "support.constant.notification.cocoa.objcpp" + }, + { + "match": "\\bNS(RuleEditor(RowType(Simple|Compound)|NestingMode(Si(ngle|mple)|Compound|List))|GradientDraws(BeforeStartingLocation|AfterEndingLocation)|M(inusSetExpressionType|a(chPortDeallocate(ReceiveRight|SendRight|None)|pTable(StrongMemory|CopyIn|ZeroingWeakMemory|ObjectPointerPersonality)))|B(oxCustom|undleExecutableArchitecture(X86|I386|PPC(64)?)|etweenPredicateOperatorType|ackgroundStyle(Raised|Dark|L(ight|owered)))|S(tring(DrawingTruncatesLastVisibleLine|EncodingConversion(ExternalRepresentation|AllowLossy))|ubqueryExpressionType|p(e(ech(SentenceBoundary|ImmediateBoundary|WordBoundary)|llingState(GrammarFlag|SpellingFlag))|litViewDividerStyleThi(n|ck))|e(rvice(RequestTimedOutError|M(iscellaneousError|alformedServiceDictionaryError)|InvalidPasteboardDataError|ErrorM(inimum|aximum)|Application(NotFoundError|LaunchFailedError))|gmentStyle(Round(Rect|ed)|SmallSquare|Capsule|Textured(Rounded|Square)|Automatic)))|H(UDWindowMask|ashTable(StrongMemory|CopyIn|ZeroingWeakMemory|ObjectPointerPersonality))|N(oModeColorPanel|etServiceNoAutoRename)|C(hangeRedone|o(ntainsPredicateOperatorType|l(orRenderingIntent(RelativeColorimetric|Saturation|Default|Perceptual|AbsoluteColorimetric)|lectorDisabledOption))|ellHit(None|ContentArea|TrackableArea|EditableTextArea))|T(imeZoneNameStyle(S(hort(Standard|DaylightSaving)|tandard)|DaylightSaving)|extFieldDatePickerStyle|ableViewSelectionHighlightStyle(Regular|SourceList)|racking(Mouse(Moved|EnteredAndExited)|CursorUpdate|InVisibleRect|EnabledDuringMouseDrag|A(ssumeInside|ctive(In(KeyWindow|ActiveApp)|WhenFirstResponder|Always))))|I(n(tersectSetExpressionType|dexedColorSpaceModel)|mageScale(None|Proportionally(Down|UpOrDown)|AxesIndependently))|Ope(nGLPFAAllowOfflineRenderers|rationQueue(DefaultMaxConcurrentOperationCount|Priority(High|Normal|Very(High|Low)|Low)))|D(iacriticInsensitiveSearch|ownloadsDirectory)|U(nionSetExpressionType|TF(16(BigEndianStringEncoding|StringEncoding|LittleEndianStringEncoding)|32(BigEndianStringEncoding|StringEncoding|LittleEndianStringEncoding)))|P(ointerFunctions(Ma(chVirtualMemory|llocMemory)|Str(ongMemory|uctPersonality)|C(StringPersonality|opyIn)|IntegerPersonality|ZeroingWeakMemory|O(paque(Memory|Personality)|bjectP(ointerPersonality|ersonality)))|at(hStyle(Standard|NavigationBar|PopUp)|ternColorSpaceModel)|rintPanelShows(Scaling|Copies|Orientation|P(a(perSize|ge(Range|SetupAccessory))|review)))|Executable(RuntimeMismatchError|NotLoadableError|ErrorM(inimum|aximum)|L(inkError|oadError)|ArchitectureMismatchError)|KeyValueObservingOption(Initial|Prior)|F(i(ndPanelSubstringMatchType(StartsWith|Contains|EndsWith|FullWord)|leRead(TooLargeError|UnknownStringEncodingError))|orcedOrderingSearch)|Wi(ndow(BackingLocation(MainMemory|Default|VideoMemory)|Sharing(Read(Only|Write)|None)|CollectionBehavior(MoveToActiveSpace|CanJoinAllSpaces|Default))|dthInsensitiveSearch)|AggregateExpressionType)\\b", + "name": "support.constant.cocoa.leopard.objcpp" + }, + { + "match": "\\bNS(R(GB(ModeColorPanel|ColorSpaceModel)|ight(Mouse(D(own(Mask)?|ragged(Mask)?)|Up(Mask)?)|T(ext(Movement|Alignment)|ab(sBezelBorder|StopType))|ArrowFunctionKey)|ound(RectBezelStyle|Bankers|ed(BezelStyle|TokenStyle|DisclosureBezelStyle)|Down|Up|Plain|Line(CapStyle|JoinStyle))|un(StoppedResponse|ContinuesResponse|AbortedResponse)|e(s(izableWindowMask|et(CursorRectsRunLoopOrdering|FunctionKey))|ce(ssedBezelStyle|iver(sCantHandleCommandScriptError|EvaluationScriptError))|turnTextMovement|doFunctionKey|quiredArgumentsMissingScriptError|l(evancyLevelIndicatorStyle|ative(Before|After))|gular(SquareBezelStyle|ControlSize)|moveTraitFontAction)|a(n(domSubelement|geDateMode)|tingLevelIndicatorStyle|dio(ModeMatrix|Button)))|G(IFFileType|lyph(Below|Inscribe(B(elow|ase)|Over(strike|Below)|Above)|Layout(WithPrevious|A(tAPoint|gainstAPoint))|A(ttribute(BidiLevel|Soft|Inscribe|Elastic)|bove))|r(ooveBorder|eaterThan(Comparison|OrEqualTo(Comparison|PredicateOperatorType)|PredicateOperatorType)|a(y(ModeColorPanel|ColorSpaceModel)|dient(None|Con(cave(Strong|Weak)|vex(Strong|Weak)))|phiteControlTint)))|XML(N(o(tationDeclarationKind|de(CompactEmptyElement|IsCDATA|OptionsNone|Use(SingleQuotes|DoubleQuotes)|Pre(serve(NamespaceOrder|C(haracterReferences|DATA)|DTD|Prefixes|E(ntities|mptyElements)|Quotes|Whitespace|A(ttributeOrder|ll))|ttyPrint)|ExpandEmptyElement))|amespaceKind)|CommentKind|TextKind|InvalidKind|D(ocument(X(MLKind|HTMLKind|Include)|HTMLKind|T(idy(XML|HTML)|extKind)|IncludeContentTypeDeclaration|Validate|Kind)|TDKind)|P(arser(GTRequiredError|XMLDeclNot(StartedError|FinishedError)|Mi(splaced(XMLDeclarationError|CDATAEndStringError)|xedContentDeclNot(StartedError|FinishedError))|S(t(andaloneValueError|ringNot(StartedError|ClosedError))|paceRequiredError|eparatorRequiredError)|N(MTOKENRequiredError|o(t(ationNot(StartedError|FinishedError)|WellBalancedError)|DTDError)|amespaceDeclarationError|AMERequiredError)|C(haracterRef(In(DTDError|PrologError|EpilogError)|AtEOFError)|o(nditionalSectionNot(StartedError|FinishedError)|mment(NotFinishedError|ContainsDoubleHyphenError))|DATANotFinishedError)|TagNameMismatchError|In(ternalError|valid(HexCharacterRefError|C(haracter(RefError|InEntityError|Error)|onditionalSectionError)|DecimalCharacterRefError|URIError|Encoding(NameError|Error)))|OutOfMemoryError|D(ocumentStartError|elegateAbortedParseError|OCTYPEDeclNotFinishedError)|U(RI(RequiredError|FragmentError)|n(declaredEntityError|parsedEntityError|knownEncodingError|finishedTagError))|P(CDATARequiredError|ublicIdentifierRequiredError|arsedEntityRef(MissingSemiError|NoNameError|In(Internal(SubsetError|Error)|PrologError|EpilogError)|AtEOFError)|r(ocessingInstructionNot(StartedError|FinishedError)|ematureDocumentEndError))|E(n(codingNotSupportedError|tity(Ref(In(DTDError|PrologError|EpilogError)|erence(MissingSemiError|WithoutNameError)|LoopError|AtEOFError)|BoundaryError|Not(StartedError|FinishedError)|Is(ParameterError|ExternalError)|ValueRequiredError))|qualExpectedError|lementContentDeclNot(StartedError|FinishedError)|xt(ernalS(tandaloneEntityError|ubsetNotFinishedError)|raContentError)|mptyDocumentError)|L(iteralNot(StartedError|FinishedError)|T(RequiredError|SlashRequiredError)|essThanSymbolInAttributeError)|Attribute(RedefinedError|HasNoValueError|Not(StartedError|FinishedError)|ListNot(StartedError|FinishedError)))|rocessingInstructionKind)|E(ntity(GeneralKind|DeclarationKind|UnparsedKind|P(ar(sedKind|ameterKind)|redefined))|lement(Declaration(MixedKind|UndefinedKind|E(lementKind|mptyKind)|Kind|AnyKind)|Kind))|Attribute(N(MToken(sKind|Kind)|otationKind)|CDATAKind|ID(Ref(sKind|Kind)|Kind)|DeclarationKind|En(tit(yKind|iesKind)|umerationKind)|Kind))|M(i(n(XEdge|iaturizableWindowMask|YEdge|uteCalendarUnit)|terLineJoinStyle|ddleSubelement|xedState)|o(nthCalendarUnit|deSwitchFunctionKey|use(Moved(Mask)?|E(ntered(Mask)?|ventSubtype|xited(Mask)?))|veToBezierPathElement|mentary(ChangeButton|Push(Button|InButton)|Light(Button)?))|enuFunctionKey|a(c(intoshInterfaceStyle|OSRomanStringEncoding)|tchesPredicateOperatorType|ppedRead|x(XEdge|YEdge))|ACHOperatingSystem)|B(MPFileType|o(ttomTabsBezelBorder|ldFontMask|rderlessWindowMask|x(Se(condary|parator)|OldStyle|Primary))|uttLineCapStyle|e(zelBorder|velLineJoinStyle|low(Bottom|Top)|gin(sWith(Comparison|PredicateOperatorType)|FunctionKey))|lueControlTint|ack(spaceCharacter|tabTextMovement|ingStore(Retained|Buffered|Nonretained)|TabCharacter|wardsSearch|groundTab)|r(owser(NoColumnResizing|UserColumnResizing|AutoColumnResizing)|eakFunctionKey))|S(h(ift(JISStringEncoding|KeyMask)|ow(ControlGlyphs|InvisibleGlyphs)|adowlessSquareBezelStyle)|y(s(ReqFunctionKey|tem(D(omainMask|efined(Mask)?)|FunctionKey))|mbolStringEncoding)|c(a(nnedOption|le(None|ToFit|Proportionally))|r(oll(er(NoPart|Increment(Page|Line|Arrow)|Decrement(Page|Line|Arrow)|Knob(Slot)?|Arrows(M(inEnd|axEnd)|None|DefaultSetting))|Wheel(Mask)?|LockFunctionKey)|eenChangedEventType))|t(opFunctionKey|r(ingDrawing(OneShot|DisableScreenFontSubstitution|Uses(DeviceMetrics|FontLeading|LineFragmentOrigin))|eam(Status(Reading|NotOpen|Closed|Open(ing)?|Error|Writing|AtEnd)|Event(Has(BytesAvailable|SpaceAvailable)|None|OpenCompleted|E(ndEncountered|rrorOccurred)))))|i(ngle(DateMode|UnderlineStyle)|ze(DownFontAction|UpFontAction))|olarisOperatingSystem|unOSOperatingSystem|pecialPageOrder|e(condCalendarUnit|lect(By(Character|Paragraph|Word)|i(ng(Next|Previous)|onAffinity(Downstream|Upstream))|edTab|FunctionKey)|gmentSwitchTracking(Momentary|Select(One|Any)))|quareLineCapStyle|witchButton|ave(ToOperation|Op(tions(Yes|No|Ask)|eration)|AsOperation)|mall(SquareBezelStyle|C(ontrolSize|apsFontMask)|IconButtonBezelStyle))|H(ighlightModeMatrix|SBModeColorPanel|o(ur(Minute(SecondDatePickerElementFlag|DatePickerElementFlag)|CalendarUnit)|rizontalRuler|meFunctionKey)|TTPCookieAcceptPolicy(Never|OnlyFromMainDocumentDomain|Always)|e(lp(ButtonBezelStyle|KeyMask|FunctionKey)|avierFontAction)|PUXOperatingSystem)|Year(MonthDa(yDatePickerElementFlag|tePickerElementFlag)|CalendarUnit)|N(o(n(StandardCharacterSetFontMask|ZeroWindingRule|activatingPanelMask|LossyASCIIStringEncoding)|Border|t(ification(SuspensionBehavior(Hold|Coalesce|D(eliverImmediately|rop))|NoCoalescing|CoalescingOn(Sender|Name)|DeliverImmediately|PostToAllSessions)|PredicateType|EqualToPredicateOperatorType)|S(cr(iptError|ollerParts)|ubelement|pecifierError)|CellMask|T(itle|opLevelContainersSpecifierError|abs(BezelBorder|NoBorder|LineBorder))|I(nterfaceStyle|mage)|UnderlineStyle|FontChangeAction)|u(ll(Glyph|CellType)|m(eric(Search|PadKeyMask)|berFormatter(Round(Half(Down|Up|Even)|Ceiling|Down|Up|Floor)|Behavior(10|Default)|S(cientificStyle|pellOutStyle)|NoStyle|CurrencyStyle|DecimalStyle|P(ercentStyle|ad(Before(Suffix|Prefix)|After(Suffix|Prefix))))))|e(t(Services(BadArgumentError|NotFoundError|C(ollisionError|ancelledError)|TimeoutError|InvalidError|UnknownError|ActivityInProgress)|workDomainMask)|wlineCharacter|xt(StepInterfaceStyle|FunctionKey))|EXTSTEPStringEncoding|a(t(iveShortGlyphPacking|uralTextAlignment)|rrowFontMask))|C(hange(ReadOtherContents|GrayCell(Mask)?|BackgroundCell(Mask)?|Cleared|Done|Undone|Autosaved)|MYK(ModeColorPanel|ColorSpaceModel)|ircular(BezelStyle|Slider)|o(n(stantValueExpressionType|t(inuousCapacityLevelIndicatorStyle|entsCellMask|ain(sComparison|erSpecifierError)|rol(Glyph|KeyMask))|densedFontMask)|lor(Panel(RGBModeMask|GrayModeMask|HSBModeMask|C(MYKModeMask|olorListModeMask|ustomPaletteModeMask|rayonModeMask)|WheelModeMask|AllModesMask)|ListModeColorPanel)|reServiceDirectory|m(p(osite(XOR|Source(In|O(ut|ver)|Atop)|Highlight|C(opy|lear)|Destination(In|O(ut|ver)|Atop)|Plus(Darker|Lighter))|ressedFontMask)|mandKeyMask))|u(stom(SelectorPredicateOperatorType|PaletteModeColorPanel)|r(sor(Update(Mask)?|PointingDevice)|veToBezierPathElement))|e(nterT(extAlignment|abStopType)|ll(State|H(ighlighted|as(Image(Horizontal|OnLeftOrBottom)|OverlappingImage))|ChangesContents|Is(Bordered|InsetButton)|Disabled|Editable|LightsBy(Gray|Background|Contents)|AllowsMixedState))|l(ipPagination|o(s(ePathBezierPathElement|ableWindowMask)|ckAndCalendarDatePickerStyle)|ear(ControlTint|DisplayFunctionKey|LineFunctionKey))|a(seInsensitive(Search|PredicateOption)|n(notCreateScriptCommandError|cel(Button|TextMovement))|chesDirectory|lculation(NoError|Overflow|DivideByZero|Underflow|LossOfPrecision)|rriageReturnCharacter)|r(itical(Request|AlertStyle)|ayonModeColorPanel))|T(hick(SquareBezelStyle|erSquareBezelStyle)|ypesetter(Behavior|HorizontalTabAction|ContainerBreakAction|ZeroAdvancementAction|OriginalBehavior|ParagraphBreakAction|WhitespaceAction|L(ineBreakAction|atestBehavior))|i(ckMark(Right|Below|Left|Above)|tledWindowMask|meZoneDatePickerElementFlag)|o(olbarItemVisibilityPriority(Standard|High|User|Low)|pTabsBezelBorder|ggleButton)|IFF(Compression(N(one|EXT)|CCITTFAX(3|4)|OldJPEG|JPEG|PackBits|LZW)|FileType)|e(rminate(Now|Cancel|Later)|xt(Read(InapplicableDocumentTypeError|WriteErrorM(inimum|aximum))|Block(M(i(nimum(Height|Width)|ddleAlignment)|a(rgin|ximum(Height|Width)))|B(o(ttomAlignment|rder)|aselineAlignment)|Height|TopAlignment|P(ercentageValueType|adding)|Width|AbsoluteValueType)|StorageEdited(Characters|Attributes)|CellType|ured(RoundedBezelStyle|BackgroundWindowMask|SquareBezelStyle)|Table(FixedLayoutAlgorithm|AutomaticLayoutAlgorithm)|Field(RoundedBezel|SquareBezel|AndStepperDatePickerStyle)|WriteInapplicableDocumentTypeError|ListPrependEnclosingMarker))|woByteGlyphPacking|ab(Character|TextMovement|le(tP(oint(Mask|EventSubtype)?|roximity(Mask|EventSubtype)?)|Column(NoResizing|UserResizingMask|AutoresizingMask)|View(ReverseSequentialColumnAutoresizingStyle|GridNone|S(olid(HorizontalGridLineMask|VerticalGridLineMask)|equentialColumnAutoresizingStyle)|NoColumnAutoresizing|UniformColumnAutoresizingStyle|FirstColumnOnlyAutoresizingStyle|LastColumnOnlyAutoresizingStyle)))|rackModeMatrix)|I(n(sert(CharFunctionKey|FunctionKey|LineFunctionKey)|t(Type|ernalS(criptError|pecifierError))|dexSubelement|validIndexSpecifierError|formational(Request|AlertStyle)|PredicateOperatorType)|talicFontMask|SO(2022JPStringEncoding|Latin(1StringEncoding|2StringEncoding))|dentityMappingCharacterCollection|llegalTextMovement|mage(R(ight|ep(MatchesDevice|LoadStatus(ReadingHeader|Completed|InvalidData|Un(expectedEOF|knownType)|WillNeedAllData)))|Below|C(ellType|ache(BySize|Never|Default|Always))|Interpolation(High|None|Default|Low)|O(nly|verlaps)|Frame(Gr(oove|ayBezel)|Button|None|Photo)|L(oadStatus(ReadError|C(ompleted|ancelled)|InvalidData|UnexpectedEOF)|eft)|A(lign(Right|Bottom(Right|Left)?|Center|Top(Right|Left)?|Left)|bove)))|O(n(State|eByteGlyphPacking|OffButton|lyScrollerArrows)|ther(Mouse(D(own(Mask)?|ragged(Mask)?)|Up(Mask)?)|TextMovement)|SF1OperatingSystem|pe(n(GL(GO(Re(setLibrary|tainRenderers)|ClearFormatCache|FormatCacheSize)|PFA(R(obust|endererID)|M(inimumPolicy|ulti(sample|Screen)|PSafe|aximumPolicy)|BackingStore|S(creenMask|te(ncilSize|reo)|ingleRenderer|upersample|ample(s|Buffers|Alpha))|NoRecovery|C(o(lor(Size|Float)|mpliant)|losestPolicy)|OffScreen|D(oubleBuffer|epthSize)|PixelBuffer|VirtualScreenCount|FullScreen|Window|A(cc(umSize|elerated)|ux(Buffers|DepthStencil)|l(phaSize|lRenderers))))|StepUnicodeReservedBase)|rationNotSupportedForKeyS(criptError|pecifierError))|ffState|KButton|rPredicateType|bjC(B(itfield|oolType)|S(hortType|tr(ingType|uctType)|electorType)|NoType|CharType|ObjectType|DoubleType|UnionType|PointerType|VoidType|FloatType|Long(Type|longType)|ArrayType))|D(i(s(c(losureBezelStyle|reteCapacityLevelIndicatorStyle)|playWindowRunLoopOrdering)|acriticInsensitivePredicateOption|rect(Selection|PredicateModifier))|o(c(ModalWindowMask|ument(Directory|ationDirectory))|ubleType|wn(TextMovement|ArrowFunctionKey))|e(s(cendingPageOrder|ktopDirectory)|cimalTabStopType|v(ice(NColorSpaceModel|IndependentModifierFlagsMask)|eloper(Directory|ApplicationDirectory))|fault(ControlTint|TokenStyle)|lete(Char(acter|FunctionKey)|FunctionKey|LineFunctionKey)|moApplicationDirectory)|a(yCalendarUnit|teFormatter(MediumStyle|Behavior(10|Default)|ShortStyle|NoStyle|FullStyle|LongStyle))|ra(wer(Clos(ingState|edState)|Open(ingState|State))|gOperation(Generic|Move|None|Copy|Delete|Private|Every|Link|All)))|U(ser(CancelledError|D(irectory|omainMask)|FunctionKey)|RL(Handle(NotLoaded|Load(Succeeded|InProgress|Failed))|CredentialPersistence(None|Permanent|ForSession))|n(scaledWindowMask|cachedRead|i(codeStringEncoding|talicFontMask|fiedTitleAndToolbarWindowMask)|d(o(CloseGroupingRunLoopOrdering|FunctionKey)|e(finedDateComponent|rline(Style(Single|None|Thick|Double)|Pattern(Solid|D(ot|ash(Dot(Dot)?)?)))))|known(ColorSpaceModel|P(ointingDevice|ageOrder)|KeyS(criptError|pecifierError))|boldFontMask)|tilityWindowMask|TF8StringEncoding|p(dateWindowsRunLoopOrdering|TextMovement|ArrowFunctionKey))|J(ustifiedTextAlignment|PEG(2000FileType|FileType)|apaneseEUC(GlyphPacking|StringEncoding))|P(o(s(t(Now|erFontMask|WhenIdle|ASAP)|iti(on(Replace|Be(fore|ginning)|End|After)|ve(IntType|DoubleType|FloatType)))|pUp(NoArrow|ArrowAt(Bottom|Center))|werOffEventType|rtraitOrientation)|NGFileType|ush(InCell(Mask)?|OnPushOffButton)|e(n(TipMask|UpperSideMask|PointingDevice|LowerSideMask)|riodic(Mask)?)|P(S(caleField|tatus(Title|Field)|aveButton)|N(ote(Title|Field)|ame(Title|Field))|CopiesField|TitleField|ImageButton|OptionsButton|P(a(perFeedButton|ge(Range(To|From)|ChoiceMatrix))|reviewButton)|LayoutButton)|lainTextTokenStyle|a(useFunctionKey|ragraphSeparatorCharacter|ge(DownFunctionKey|UpFunctionKey))|r(int(ing(ReplyLater|Success|Cancelled|Failure)|ScreenFunctionKey|erTable(NotFound|OK|Error)|FunctionKey)|o(p(ertyList(XMLFormat|MutableContainers(AndLeaves)?|BinaryFormat|Immutable|OpenStepFormat)|rietaryStringEncoding)|gressIndicator(BarStyle|SpinningStyle|Preferred(SmallThickness|Thickness|LargeThickness|AquaThickness)))|e(ssedTab|vFunctionKey))|L(HeightForm|CancelButton|TitleField|ImageButton|O(KButton|rientationMatrix)|UnitsButton|PaperNameButton|WidthForm))|E(n(terCharacter|d(sWith(Comparison|PredicateOperatorType)|FunctionKey))|v(e(nOddWindingRule|rySubelement)|aluatedObjectExpressionType)|qualTo(Comparison|PredicateOperatorType)|ra(serPointingDevice|CalendarUnit|DatePickerElementFlag)|x(clude(10|QuickDrawElementsIconCreationOption)|pandedFontMask|ecuteFunctionKey))|V(i(ew(M(in(XMargin|YMargin)|ax(XMargin|YMargin))|HeightSizable|NotSizable|WidthSizable)|aPanelFontAction)|erticalRuler|a(lidationErrorM(inimum|aximum)|riableExpressionType))|Key(SpecifierEvaluationScriptError|Down(Mask)?|Up(Mask)?|PathExpressionType|Value(MinusSetMutation|SetSetMutation|Change(Re(placement|moval)|Setting|Insertion)|IntersectSetMutation|ObservingOption(New|Old)|UnionSetMutation|ValidationError))|QTMovie(NormalPlayback|Looping(BackAndForthPlayback|Playback))|F(1(1FunctionKey|7FunctionKey|2FunctionKey|8FunctionKey|3FunctionKey|9FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey|6FunctionKey)|7FunctionKey|i(nd(PanelAction(Replace(A(ndFind|ll(InSelection)?))?|S(howFindPanel|e(tFindString|lectAll(InSelection)?))|Next|Previous)|FunctionKey)|tPagination|le(Read(No(SuchFileError|PermissionError)|CorruptFileError|In(validFileNameError|applicableStringEncodingError)|Un(supportedSchemeError|knownError))|HandlingPanel(CancelButton|OKButton)|NoSuchFileError|ErrorM(inimum|aximum)|Write(NoPermissionError|In(validFileNameError|applicableStringEncodingError)|OutOfSpaceError|Un(supportedSchemeError|knownError))|LockingError)|xedPitchFontMask)|2(1FunctionKey|7FunctionKey|2FunctionKey|8FunctionKey|3FunctionKey|9FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey|6FunctionKey)|o(nt(Mo(noSpaceTrait|dernSerifsClass)|BoldTrait|S(ymbolicClass|criptsClass|labSerifsClass|ansSerifClass)|C(o(ndensedTrait|llectionApplicationOnlyMask)|larendonSerifsClass)|TransitionalSerifsClass|I(ntegerAdvancementsRenderingMode|talicTrait)|O(ldStyleSerifsClass|rnamentalsClass)|DefaultRenderingMode|U(nknownClass|IOptimizedTrait)|Panel(S(hadowEffectModeMask|t(andardModesMask|rikethroughEffectModeMask)|izeModeMask)|CollectionModeMask|TextColorEffectModeMask|DocumentColorEffectModeMask|UnderlineEffectModeMask|FaceModeMask|All(ModesMask|EffectsModeMask))|ExpandedTrait|VerticalTrait|F(amilyClassMask|reeformSerifsClass)|Antialiased(RenderingMode|IntegerAdvancementsRenderingMode))|cusRing(Below|Type(None|Default|Exterior)|Only|Above)|urByteGlyphPacking|rm(attingError(M(inimum|aximum))?|FeedCharacter))|8FunctionKey|unction(ExpressionType|KeyMask)|3(1FunctionKey|2FunctionKey|3FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey)|9FunctionKey|4FunctionKey|P(RevertButton|S(ize(Title|Field)|etButton)|CurrentField|Preview(Button|Field))|l(oat(ingPointSamplesBitmapFormat|Type)|agsChanged(Mask)?)|axButton|5FunctionKey|6FunctionKey)|W(heelModeColorPanel|indow(s(NTOperatingSystem|CP125(1StringEncoding|2StringEncoding|3StringEncoding|4StringEncoding|0StringEncoding)|95(InterfaceStyle|OperatingSystem))|M(iniaturizeButton|ovedEventType)|Below|CloseButton|ToolbarButton|ZoomButton|Out|DocumentIconButton|ExposedEventType|Above)|orkspaceLaunch(NewInstance|InhibitingBackgroundOnly|Default|PreferringClassic|WithoutA(ctivation|ddingToRecents)|A(sync|nd(Hide(Others)?|Print)|llowingClassicStartup))|eek(day(CalendarUnit|OrdinalCalendarUnit)|CalendarUnit)|a(ntsBidiLevels|rningAlertStyle)|r(itingDirection(RightToLeft|Natural|LeftToRight)|apCalendarComponents))|L(i(stModeMatrix|ne(Moves(Right|Down|Up|Left)|B(order|reakBy(C(harWrapping|lipping)|Truncating(Middle|Head|Tail)|WordWrapping))|S(eparatorCharacter|weep(Right|Down|Up|Left))|ToBezierPathElement|DoesntMove|arSlider)|teralSearch|kePredicateOperatorType|ghterFontAction|braryDirectory)|ocalDomainMask|e(ssThan(Comparison|OrEqualTo(Comparison|PredicateOperatorType)|PredicateOperatorType)|ft(Mouse(D(own(Mask)?|ragged(Mask)?)|Up(Mask)?)|T(ext(Movement|Alignment)|ab(sBezelBorder|StopType))|ArrowFunctionKey))|a(yout(RightToLeft|NotDone|CantFit|OutOfGlyphs|Done|LeftToRight)|ndscapeOrientation)|ABColorSpaceModel)|A(sc(iiWithDoubleByteEUCGlyphPacking|endingPageOrder)|n(y(Type|PredicateModifier|EventMask)|choredSearch|imation(Blocking|Nonblocking(Threaded)?|E(ffect(DisappearingItemDefault|Poof)|ase(In(Out)?|Out))|Linear)|dPredicateType)|t(Bottom|tachmentCharacter|omicWrite|Top)|SCIIStringEncoding|d(obe(GB1CharacterCollection|CNS1CharacterCollection|Japan(1CharacterCollection|2CharacterCollection)|Korea1CharacterCollection)|dTraitFontAction|minApplicationDirectory)|uto(saveOperation|Pagination)|pp(lication(SupportDirectory|D(irectory|e(fined(Mask)?|legateReply(Success|Cancel|Failure)|activatedEventType))|ActivatedEventType)|KitDefined(Mask)?)|l(ternateKeyMask|pha(ShiftKeyMask|NonpremultipliedBitmapFormat|FirstBitmapFormat)|ert(SecondButtonReturn|ThirdButtonReturn|OtherReturn|DefaultReturn|ErrorReturn|FirstButtonReturn|AlternateReturn)|l(ScrollerParts|DomainsMask|PredicateModifier|LibrariesDirectory|ApplicationsDirectory))|rgument(sWrongScriptError|EvaluationScriptError)|bove(Bottom|Top)|WTEventType))\\b", + "name": "support.constant.cocoa.objcpp" + }, + { + "include": "#c_lang" + }, + { + "include": "#bracketed_content" } - ] + ], + "repository": { + "c_lang": { + "patterns": [ + { + "include": "#preprocessor-rule-enabled" + }, + { + "include": "#preprocessor-rule-disabled" + }, + { + "include": "#preprocessor-rule-conditional" + }, + { + "include": "#comments" + }, + { + "include": "#switch_statement" + }, + { + "match": "\\b(break|continue|do|else|for|goto|if|_Pragma|return|while)\\b", + "name": "keyword.control.objcpp" + }, + { + "include": "#storage_types" + }, + { + "match": "typedef", + "name": "keyword.other.typedef.objcpp" + }, + { + "match": "\\b(const|extern|register|restrict|static|volatile|inline)\\b", + "name": "storage.modifier.objcpp" + }, + { + "match": "\\bk[A-Z]\\w*\\b", + "name": "constant.other.variable.mac-classic.objcpp" + }, + { + "match": "\\bg[A-Z]\\w*\\b", + "name": "variable.other.readwrite.global.mac-classic.objcpp" + }, + { + "match": "\\bs[A-Z]\\w*\\b", + "name": "variable.other.readwrite.static.mac-classic.objcpp" + }, + { + "match": "\\b(NULL|true|false|TRUE|FALSE)\\b", + "name": "constant.language.objcpp" + }, + { + "include": "#operators" + }, + { + "include": "#numbers" + }, + { + "include": "#strings" + }, + { + "begin": "(?x)\n^\\s* ((\\#)\\s*define) \\s+\t# define\n((?[a-zA-Z_$][\\w$]*))\t # macro name\n(?:\n (\\()\n\t(\n\t \\s* \\g \\s*\t\t # first argument\n\t ((,) \\s* \\g \\s*)* # additional arguments\n\t (?:\\.\\.\\.)?\t\t\t# varargs ellipsis?\n\t)\n (\\))\n)?", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.define.objcpp" + }, + "2": { + "name": "punctuation.definition.directive.objcpp" + }, + "3": { + "name": "entity.name.function.preprocessor.objcpp" + }, + "5": { + "name": "punctuation.definition.parameters.begin.objcpp" + }, + "6": { + "name": "variable.parameter.preprocessor.objcpp" + }, + "8": { + "name": "punctuation.separator.parameters.objcpp" + }, + "9": { + "name": "punctuation.definition.parameters.end.objcpp" + } + }, + "end": "(?=(?://|/\\*))|(?", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objcpp" + } + }, + "name": "string.quoted.other.lt-gt.include.objcpp" + } + ] + }, + { + "include": "#pragma-mark" + }, + { + "begin": "^\\s*((#)\\s*line)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.line.objcpp" + }, + "2": { + "name": "punctuation.definition.directive.objcpp" + } + }, + "end": "(?=(?://|/\\*))|(?\\]\\)]))\\s*([a-zA-Z_]\\w*)\\s*(?=(?:\\[\\]\\s*)?(?:,|\\)))", + "captures": { + "1": { + "name": "variable.parameter.probably.objcpp" + } + } + }, + "access-method": { + "name": "meta.function-call.member.objcpp", + "begin": "([a-zA-Z_][a-zA-Z_0-9]*|(?<=[\\]\\)]))\\s*(?:(\\.)|(->))((?:(?:[a-zA-Z_][a-zA-Z_0-9]*)\\s*(?:(?:\\.)|(?:->)))*)\\s*([a-zA-Z_][a-zA-Z_0-9]*)(\\()", + "beginCaptures": { + "1": { + "name": "variable.object.objcpp" + }, + "2": { + "name": "punctuation.separator.dot-access.objcpp" + }, + "3": { + "name": "punctuation.separator.pointer-access.objcpp" + }, + "4": { + "patterns": [ + { + "match": "\\.", + "name": "punctuation.separator.dot-access.objcpp" + }, + { + "match": "->", + "name": "punctuation.separator.pointer-access.objcpp" + }, + { + "match": "[a-zA-Z_][a-zA-Z_0-9]*", + "name": "variable.object.objcpp" + }, + { + "name": "everything.else.objcpp", + "match": ".+" + } + ] + }, + "5": { + "name": "entity.name.function.member.objcpp" + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.function.member.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.arguments.end.bracket.round.function.member.objcpp" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + "block": { + "patterns": [ + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objcpp" + } + }, + "end": "}|(?=\\s*#\\s*(?:elif|else|endif)\\b)", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.bracket.curly.objcpp" + } + }, + "name": "meta.block.objcpp", + "patterns": [ + { + "include": "#block_innards" + } + ] + } + ] + }, + "block_innards": { + "patterns": [ + { + "include": "#preprocessor-rule-enabled-block" + }, + { + "include": "#preprocessor-rule-disabled-block" + }, + { + "include": "#preprocessor-rule-conditional-block" + }, + { + "include": "#method_access" + }, + { + "include": "#member_access" + }, + { + "include": "#c_function_call" + }, + { + "name": "meta.initialization.objcpp", + "begin": "(?x)\n(?:\n (?:\n\t(?=\\s)(?=+!]+ | \\(\\) | \\[\\]))\n)\n\\s*(\\() # opening bracket", + "beginCaptures": { + "1": { + "name": "variable.other.objcpp" + }, + "2": { + "name": "punctuation.section.parens.begin.bracket.round.initialization.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.initialization.objcpp" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objcpp" + } + }, + "end": "}|(?=\\s*#\\s*(?:elif|else|endif)\\b)", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.bracket.curly.objcpp" + } + }, + "patterns": [ + { + "include": "#block_innards" + } + ] + }, + { + "include": "#parens-block" + }, + { + "include": "$base" + } + ] + }, + "c_function_call": { + "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate|and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas)\\s*\\()\n(?=\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++\\s*\\( # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", + "end": "(?<=\\))(?!\\w)", + "name": "meta.function-call.objcpp", + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + "comments": { + "patterns": [ + { + "captures": { + "1": { + "name": "meta.toc-list.banner.block.objcpp" + } + }, + "match": "^/\\* =(\\s*.*?)\\s*= \\*/$\\n?", + "name": "comment.block.objcpp" + }, + { + "begin": "/\\*", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.begin.objcpp" + } + }, + "end": "\\*/", + "endCaptures": { + "0": { + "name": "punctuation.definition.comment.end.objcpp" + } + }, + "name": "comment.block.objcpp" + }, + { + "captures": { + "1": { + "name": "meta.toc-list.banner.line.objcpp" + } + }, + "match": "^// =(\\s*.*?)\\s*=\\s*$\\n?", + "name": "comment.line.banner.objcpp" + }, + { + "begin": "(^[ \\t]+)?(?=//)", + "beginCaptures": { + "1": { + "name": "punctuation.whitespace.comment.leading.objcpp" + } + }, + "end": "(?!\\G)", + "patterns": [ + { + "begin": "//", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.objcpp" + } + }, + "end": "(?=\\n)", + "name": "comment.line.double-slash.objcpp", + "patterns": [ + { + "include": "#line_continuation_character" + } + ] + } + ] + } + ] + }, + "disabled": { + "begin": "^\\s*#\\s*if(n?def)?\\b.*$", + "end": "^\\s*#\\s*endif\\b", + "patterns": [ + { + "include": "#disabled" + }, + { + "include": "#pragma-mark" + } + ] + }, + "line_continuation_character": { + "patterns": [ + { + "match": "(\\\\)\\n", + "captures": { + "1": { + "name": "constant.character.escape.line-continuation.objcpp" + } + } + } + ] + }, + "parens": { + "name": "meta.parens.objcpp", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + "parens-block": { + "name": "meta.parens.block.objcpp", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "#block_innards" + }, + { + "match": "(?-mix:(?>=|\\|=", + "name": "keyword.operator.assignment.compound.bitwise.objcpp" + }, + { + "match": "<<|>>", + "name": "keyword.operator.bitwise.shift.objcpp" + }, + { + "match": "!=|<=|>=|==|<|>", + "name": "keyword.operator.comparison.objcpp" + }, + { + "match": "&&|!|\\|\\|", + "name": "keyword.operator.logical.objcpp" + }, + { + "match": "&|\\||\\^|~", + "name": "keyword.operator.objcpp" + }, + { + "match": "=", + "name": "keyword.operator.assignment.objcpp" + }, + { + "match": "%|\\*|/|-|\\+", + "name": "keyword.operator.objcpp" + }, + { + "begin": "(\\?)", + "beginCaptures": { + "1": { + "name": "keyword.operator.ternary.objcpp" + } + }, + "end": "(:)", + "endCaptures": { + "1": { + "name": "keyword.operator.ternary.objcpp" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + }, + { + "include": "$base" + } + ] + } + ] + }, + "strings": { + "patterns": [ + { + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.objcpp" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objcpp" + } + }, + "name": "string.quoted.double.objcpp", + "patterns": [ + { + "include": "#string_escaped_char" + }, + { + "include": "#string_placeholder" + }, + { + "include": "#line_continuation_character" + } + ] + }, + { + "begin": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.objcpp" + } + }, + "end": "'", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objcpp" + } + }, + "name": "string.quoted.single.objcpp", + "patterns": [ + { + "include": "#string_escaped_char" + }, + { + "include": "#line_continuation_character" + } + ] + } + ] + }, + "string_escaped_char": { + "patterns": [ + { + "match": "(?x)\\\\ (\n\\\\\t\t\t |\n[abefnprtv'\"?] |\n[0-3]\\d{,2}\t |\n[4-7]\\d?\t\t|\nx[a-fA-F0-9]{,2} |\nu[a-fA-F0-9]{,4} |\nU[a-fA-F0-9]{,8} )", + "name": "constant.character.escape.objcpp" + }, + { + "match": "\\\\.", + "name": "invalid.illegal.unknown-escape.objcpp" + } + ] + }, + "string_placeholder": { + "patterns": [ + { + "match": "(?x) %\n(\\d+\\$)?\t\t\t\t\t\t # field (argument #)\n[#0\\- +']*\t\t\t\t\t\t # flags\n[,;:_]?\t\t\t\t\t\t\t # separator character (AltiVec)\n((-?\\d+)|\\*(-?\\d+\\$)?)?\t\t # minimum field width\n(\\.((-?\\d+)|\\*(-?\\d+\\$)?)?)?\t# precision\n(hh|h|ll|l|j|t|z|q|L|vh|vl|v|hv|hl)? # length modifier\n[diouxXDOUeEfFgGaACcSspn%]\t\t # conversion type", + "name": "constant.other.placeholder.objcpp" + }, + { + "match": "(%)(?!\"\\s*(PRI|SCN))", + "captures": { + "1": { + "name": "invalid.illegal.placeholder.objcpp" + } + } + } + ] + }, + "storage_types": { + "patterns": [ + { + "match": "(?-mix:(?=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", + "end": "(?<=\\))(?!\\w)|(?=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.objcpp" + }, + "2": { + "name": "punctuation.section.arguments.begin.bracket.round.objcpp" + } + }, + "end": "(\\))|(?=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.objcpp" + }, + "2": { + "name": "punctuation.section.parameters.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parameters.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "#probably_a_parameter" + }, + { + "include": "#function-innards" + } + ] + }, + { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "#function-innards" + } + ] + }, + { + "include": "$base" + } + ] + }, + "function-call-innards": { + "patterns": [ + { + "include": "#comments" + }, + { + "include": "#storage_types" + }, + { + "include": "#method_access" + }, + { + "include": "#member_access" + }, + { + "include": "#operators" + }, + { + "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate|and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas)\\s*\\()\n(\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++ # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.objcpp" + }, + "2": { + "name": "punctuation.section.arguments.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.arguments.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + { + "include": "#block_innards" + } + ] + }, + "default_statement": { + "name": "meta.conditional.case.objcpp", + "begin": "((?\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.switch.objcpp", + "begin": "\\G ?", + "end": "((?:\\{|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.switch.objcpp" + } + }, + "patterns": [ + { + "include": "#switch_conditional_parentheses" + }, + { + "include": "$base" + } + ] + }, + { + "name": "meta.body.switch.objcpp", + "begin": "(?<=\\{)", + "end": "(\\})", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.switch.objcpp" + } + }, + "patterns": [ + { + "include": "#default_statement" + }, + { + "include": "#case_statement" + }, + { + "include": "$base" + }, + { + "include": "#block_innards" + } + ] + }, + { + "name": "meta.tail.switch.objcpp", + "begin": "(?<=})[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$base" + } + ] + } + ] + }, + "switch_conditional_parentheses": { + "name": "meta.conditional.switch.objcpp", + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.section.parens.begin.bracket.round.conditional.switch.objcpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.conditional.switch.objcpp" + } + }, + "patterns": [ + { + "include": "#conditional_context" + } + ] + }, + "static_assert": { + "begin": "(static_assert|_Static_assert)\\s*(\\()", + "beginCaptures": { + "1": { + "name": "keyword.other.static_assert.objcpp" + }, + "2": { + "name": "punctuation.section.arguments.begin.bracket.round.objcpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "name": "meta.static_assert.message.objcpp", + "begin": "(,)\\s*(?=(?:L|u8|u|U\\s*\\\")?)", + "beginCaptures": { + "1": { + "name": "punctuation.separator.delimiter.objcpp" + } + }, + "end": "(?=\\))", + "patterns": [ + { + "include": "#string_context" + }, + { + "include": "#string_context_c" + } + ] + }, + { + "include": "#function_call_context" + } + ] + }, + "conditional_context": { + "patterns": [ + { + "include": "$base" + }, + { + "include": "#block_innards" + } + ] + }, + "member_access": { + "match": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))((?:[a-zA-Z_]\\w*\\s*(?-mix:(?:(?:\\.\\*|\\.))|(?:(?:->\\*|->)))\\s*)*)\\s*(\\b(?!(?:void|char|short|int|signed|unsigned|long|float|double|bool|_Bool|_Complex|_Imaginary|u_char|u_short|u_int|u_long|ushort|uint|u_quad_t|quad_t|qaddr_t|caddr_t|daddr_t|div_t|dev_t|fixpt_t|blkcnt_t|blksize_t|gid_t|in_addr_t|in_port_t|ino_t|key_t|mode_t|nlink_t|id_t|pid_t|off_t|segsz_t|swblk_t|uid_t|id_t|clock_t|size_t|ssize_t|time_t|useconds_t|suseconds_t|pthread_attr_t|pthread_cond_t|pthread_condattr_t|pthread_mutex_t|pthread_mutexattr_t|pthread_once_t|pthread_rwlock_t|pthread_rwlockattr_t|pthread_t|pthread_key_t|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|int_least8_t|int_least16_t|int_least32_t|int_least64_t|uint_least8_t|uint_least16_t|uint_least32_t|uint_least64_t|int_fast8_t|int_fast16_t|int_fast32_t|int_fast64_t|uint_fast8_t|uint_fast16_t|uint_fast32_t|uint_fast64_t|intptr_t|uintptr_t|intmax_t|intmax_t|uintmax_t|uintmax_t|memory_order|atomic_bool|atomic_char|atomic_schar|atomic_uchar|atomic_short|atomic_ushort|atomic_int|atomic_uint|atomic_long|atomic_ulong|atomic_llong|atomic_ullong|atomic_char16_t|atomic_char32_t|atomic_wchar_t|atomic_int_least8_t|atomic_uint_least8_t|atomic_int_least16_t|atomic_uint_least16_t|atomic_int_least32_t|atomic_uint_least32_t|atomic_int_least64_t|atomic_uint_least64_t|atomic_int_fast8_t|atomic_uint_fast8_t|atomic_int_fast16_t|atomic_uint_fast16_t|atomic_int_fast32_t|atomic_uint_fast32_t|atomic_int_fast64_t|atomic_uint_fast64_t|atomic_intptr_t|atomic_uintptr_t|atomic_size_t|atomic_ptrdiff_t|atomic_intmax_t|atomic_uintmax_t))[a-zA-Z_]\\w*\\b(?!\\())", + "captures": { + "1": { + "name": "variable.other.object.access.objcpp" + }, + "2": { + "name": "punctuation.separator.dot-access.objcpp" + }, + "3": { + "name": "punctuation.separator.pointer-access.objcpp" + }, + "4": { + "patterns": [ + { + "include": "#member_access" + }, + { + "include": "#method_access" + }, + { + "match": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))", + "captures": { + "1": { + "name": "variable.other.object.access.objcpp" + }, + "2": { + "name": "punctuation.separator.dot-access.objcpp" + }, + "3": { + "name": "punctuation.separator.pointer-access.objcpp" + } + } + } + ] + }, + "5": { + "name": "variable.other.member.objcpp" + } + } + }, + "method_access": { + "contentName": "meta.function-call.member.objcpp", + "begin": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))((?:[a-zA-Z_]\\w*\\s*(?-mix:(?:(?:\\.\\*|\\.))|(?:(?:->\\*|->)))\\s*)*)\\s*([a-zA-Z_]\\w*)(\\()", + "beginCaptures": { + "1": { + "name": "variable.other.object.access.objcpp" + }, + "2": { + "name": "punctuation.separator.dot-access.objcpp" + }, + "3": { + "name": "punctuation.separator.pointer-access.objcpp" + }, + "4": { + "patterns": [ + { + "include": "#member_access" + }, + { + "include": "#method_access" + }, + { + "match": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))", + "captures": { + "1": { + "name": "variable.other.object.access.objcpp" + }, + "2": { + "name": "punctuation.separator.dot-access.objcpp" + }, + "3": { + "name": "punctuation.separator.pointer-access.objcpp" + } + } + } + ] + }, + "5": { + "name": "entity.name.function.member.objcpp" + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.function.member.objcpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.function.member.objcpp" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + "numbers": { + "begin": "(?", + "endCaptures": { + "0": { + "name": "meta.template.angle-brackets.end.objcpp" + } + }, + "name": "template.definition.objcpp", + "patterns": [ + { + "include": "#template_definition_argument" + } + ] + }, + "template_definition_argument": { + "match": "\\s*(?:([a-zA-Z_][a-zA-Z_0-9]*\\s*)|((?:[a-zA-Z_][a-zA-Z_0-9]*\\s+)*)([a-zA-Z_][a-zA-Z_0-9]*)|([a-zA-Z_][a-zA-Z_0-9]*)\\s*(\\.\\.\\.)\\s*([a-zA-Z_][a-zA-Z_0-9]*)|((?:[a-zA-Z_][a-zA-Z_0-9]*\\s+)*)([a-zA-Z_][a-zA-Z_0-9]*)\\s*(=)\\s*(\\w+))(,|(?=>))", + "captures": { + "1": { + "name": "storage.type.template.objcpp" + }, + "2": { + "name": "storage.type.template.objcpp" + }, + "3": { + "name": "entity.name.type.template.objcpp" + }, + "4": { + "name": "storage.type.template.objcpp" + }, + "5": { + "name": "meta.template.operator.ellipsis.objcpp" + }, + "6": { + "name": "entity.name.type.template.objcpp" + }, + "7": { + "name": "storage.type.template.objcpp" + }, + "8": { + "name": "entity.name.type.template.objcpp" + }, + "9": { + "name": "keyword.operator.assignment.objcpp" + }, + "10": { + "name": "constant.language.objcpp" + }, + "11": { + "name": "meta.template.operator.comma.objcpp" + } + } + }, + "angle_brackets": { + "begin": "<", + "end": ">", + "name": "meta.angle-brackets.objcpp", + "patterns": [ + { + "include": "#angle_brackets" + }, + { + "include": "$base" + } + ] + }, + "block": { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objcpp" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.bracket.curly.objcpp" + } + }, + "name": "meta.block.objcpp", + "patterns": [ + { + "captures": { + "1": { + "name": "support.function.any-method.objcpp" + }, + "2": { + "name": "punctuation.definition.parameters.objcpp" + } + }, + "match": "(?x)\n(\n (?!while|for|do|if|else|switch|catch|enumerate|return|r?iterate)\n (?:\\b[A-Za-z_][A-Za-z0-9_]*+\\b|::)*+ # actual name\n)\n\\s*(\\() # opening bracket", + "name": "meta.function-call.objcpp" + }, + { + "include": "$base" + } + ] + }, + "constructor": { + "patterns": [ + { + "begin": "(?x)\n(?:^\\s*) # beginning of line\n((?!while|for|do|if|else|switch|catch|enumerate|r?iterate)[A-Za-z_][A-Za-z0-9_:]*) # actual name\n\\s*(\\() # opening bracket", + "beginCaptures": { + "1": { + "name": "entity.name.function.constructor.objcpp" + }, + "2": { + "name": "punctuation.definition.parameters.begin.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.objcpp" + } + }, + "name": "meta.function.constructor.objcpp", + "patterns": [ + { + "include": "#probably_a_parameter" + }, + { + "include": "#function-innards" + } + ] + }, + { + "begin": "(?x)\n(:)\n(\n (?=\n \\s*[A-Za-z_][A-Za-z0-9_:]* # actual name\n \\s* (\\() # opening bracket\n )\n)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.parameters.objcpp" + } + }, + "end": "(?=\\{)", + "name": "meta.function.constructor.initializer-list.objcpp", + "patterns": [ + { + "include": "$base" + } + ] + } + ] + }, + "special_block": { + "patterns": [ + { + "begin": "\\b(using)\\b\\s*(namespace)\\b\\s*((?:[_A-Za-z][_A-Za-z0-9]*\\b(::)?)*)", + "beginCaptures": { + "1": { + "name": "keyword.control.objcpp" + }, + "2": { + "name": "storage.type.namespace.objcpp" + }, + "3": { + "name": "entity.name.type.objcpp" + } + }, + "end": ";", + "endCaptures": { + "0": { + "name": "punctuation.terminator.statement.objcpp" + } + }, + "name": "meta.using-namespace-declaration.objcpp" + }, + { + "begin": "\\b(namespace)\\b\\s*([_A-Za-z][_A-Za-z0-9]*\\b)?+", + "beginCaptures": { + "1": { + "name": "storage.type.namespace.objcpp" + }, + "2": { + "name": "entity.name.type.objcpp" + } + }, + "captures": { + "1": { + "name": "keyword.control.namespace.$2.objcpp" + } + }, + "end": "(?<=\\})|(?=(;|,|\\(|\\)|>|\\[|\\]|=))", + "name": "meta.namespace-block.objcpp", + "patterns": [ + { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.scope.objcpp" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.scope.objcpp" + } + }, + "patterns": [ + { + "include": "#special_block" + }, + { + "include": "#constructor" + }, + { + "include": "$base" + } + ] + }, + { + "include": "$base" + } + ] + }, + { + "begin": "\\b(?:(class)|(struct))\\b\\s*([_A-Za-z][_A-Za-z0-9]*\\b)?+(\\s*:\\s*(public|protected|private)\\s*([_A-Za-z][_A-Za-z0-9]*\\b)((\\s*,\\s*(public|protected|private)\\s*[_A-Za-z][_A-Za-z0-9]*\\b)*))?", + "beginCaptures": { + "1": { + "name": "storage.type.class.objcpp" + }, + "2": { + "name": "storage.type.struct.objcpp" + }, + "3": { + "name": "entity.name.type.objcpp" + }, + "5": { + "name": "storage.type.modifier.access.objcpp" + }, + "6": { + "name": "entity.name.type.inherited.objcpp" + }, + "7": { + "patterns": [ + { + "match": "(public|protected|private)", + "name": "storage.type.modifier.access.objcpp" + }, + { + "match": "[_A-Za-z][_A-Za-z0-9]*", + "name": "entity.name.type.inherited.objcpp" + } + ] + } + }, + "end": "(?<=\\})|(?=(;|\\(|\\)|>|\\[|\\]|=))", + "name": "meta.class-struct-block.objcpp", + "patterns": [ + { + "include": "#angle_brackets" + }, + { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objcpp" + } + }, + "end": "(\\})(\\s*\\n)?", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.objcpp" + }, + "2": { + "name": "invalid.illegal.you-forgot-semicolon.objcpp" + } + }, + "patterns": [ + { + "include": "#special_block" + }, + { + "include": "#constructor" + }, + { + "include": "$base" + } + ] + }, + { + "include": "$base" + } + ] + }, + { + "begin": "\\b(extern)(?=\\s*\")", + "beginCaptures": { + "1": { + "name": "storage.modifier.objcpp" + } + }, + "end": "(?<=\\})|(?=\\w)|(?=\\s*#\\s*endif\\b)", + "name": "meta.extern-block.objcpp", + "patterns": [ + { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objcpp" + } + }, + "end": "\\}|(?=\\s*#\\s*endif\\b)", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.bracket.curly.objcpp" + } + }, + "patterns": [ + { + "include": "#special_block" + }, + { + "include": "$base" + } + ] + }, + { + "include": "$base" + } + ] + } + ] + }, + "strings": { + "patterns": [ + { + "begin": "(u|u8|U|L)?\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.objcpp" + }, + "1": { + "name": "meta.encoding.objcpp" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objcpp" + } + }, + "name": "string.quoted.double.objcpp", + "patterns": [ + { + "match": "\\\\u\\h{4}|\\\\U\\h{8}", + "name": "constant.character.escape.objcpp" + }, + { + "match": "\\\\['\"?\\\\abfnrtv]", + "name": "constant.character.escape.objcpp" + }, + { + "match": "\\\\[0-7]{1,3}", + "name": "constant.character.escape.objcpp" + }, + { + "match": "\\\\x\\h+", + "name": "constant.character.escape.objcpp" + }, + { + "include": "#string_placeholder" + } + ] + }, + { + "begin": "(u|u8|U|L)?R\"(?:([^ ()\\\\\\t]{0,16})|([^ ()\\\\\\t]*))\\(", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.objcpp" + }, + "1": { + "name": "meta.encoding.objcpp" + }, + "3": { + "name": "invalid.illegal.delimiter-too-long.objcpp" + } + }, + "end": "\\)\\2(\\3)\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objcpp" + }, + "1": { + "name": "invalid.illegal.delimiter-too-long.objcpp" + } + }, + "name": "string.quoted.double.raw.objcpp" + } + ] + } + } + }, + "cpp_lang_newish": { + "patterns": [ + { + "include": "#special_block" + }, + { + "match": "(?-mix:##[a-zA-Z_]\\w*(?!\\w))", + "name": "variable.other.macro.argument.objcpp" + }, + { + "include": "#strings" + }, + { + "match": "(?[a-zA-Z_$][\\w$]*))\t # macro name\n(?:\n (\\()\n\t(\n\t \\s* \\g \\s*\t\t # first argument\n\t ((,) \\s* \\g \\s*)* # additional arguments\n\t (?:\\.\\.\\.)?\t\t\t# varargs ellipsis?\n\t)\n (\\))\n)?", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.define.objcpp" + }, + "2": { + "name": "punctuation.definition.directive.objcpp" + }, + "3": { + "name": "entity.name.function.preprocessor.objcpp" + }, + "5": { + "name": "punctuation.definition.parameters.begin.objcpp" + }, + "6": { + "name": "variable.parameter.preprocessor.objcpp" + }, + "8": { + "name": "punctuation.separator.parameters.objcpp" + }, + "9": { + "name": "punctuation.definition.parameters.end.objcpp" + } + }, + "end": "(?=(?://|/\\*))|(?", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objcpp" + } + }, + "name": "string.quoted.other.lt-gt.include.objcpp" + } + ] + }, + { + "include": "#pragma-mark" + }, + { + "begin": "^\\s*((#)\\s*line)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.line.objcpp" + }, + "2": { + "name": "punctuation.definition.directive.objcpp" + } + }, + "end": "(?=(?://|/\\*))|(?,\\w])*>\\s*", + "captures": { + "0": { + "name": "meta.template.call.objcpp", + "patterns": [ + { + "include": "#storage_types_c" + }, + { + "include": "#constants" + }, + { + "include": "#scope_resolution" + }, + { + "match": "(?))", + "endCaptures": { + "1": { + "name": "punctuation.section.angle-brackets.end.template.definition.objcpp" + } + }, + "patterns": [ + { + "include": "#scope_resolution" + }, + { + "include": "#template_definition_argument" + }, + { + "include": "#template_call_innards" + } + ] + }, + "template_definition_argument": { + "match": "((?:(?:(?:(?:(?:(?:\\s*([a-zA-Z_]\\w*)|((?:[a-zA-Z_]\\w*\\s+)+)([a-zA-Z_]\\w*)))|([a-zA-Z_]\\w*)\\s*(\\.\\.\\.)\\s*([a-zA-Z_]\\w*)))|((?:[a-zA-Z_]\\w*\\s+)*)([a-zA-Z_]\\w*)\\s*([=])\\s*(\\w+)))\\s*(?:(?:(,)|(?=>))))", + "captures": { + "2": { + "name": "storage.type.template.argument.$1.objcpp" + }, + "3": { + "name": "storage.type.template.argument.$2.objcpp" + }, + "4": { + "name": "entity.name.type.template.objcpp" + }, + "5": { + "name": "storage.type.template.objcpp" + }, + "6": { + "name": "keyword.operator.ellipsis.template.definition.objcpp" + }, + "7": { + "name": "entity.name.type.template.objcpp" + }, + "8": { + "name": "storage.type.template.objcpp" + }, + "9": { + "name": "entity.name.type.template.objcpp" + }, + "10": { + "name": "keyword.operator.assignment.objcpp" + }, + "11": { + "name": "constant.other.objcpp" + }, + "12": { + "name": "punctuation.separator.comma.template.argument.objcpp" + } + } + }, + "scope_resolution": { + "match": "((?:[a-zA-Z_]\\w*\\s*(?:(?:<(?:[\\s<>,\\w])*>\\s*))?::)*\\s*)([a-zA-Z_]\\w*)\\s*((?:<(?:[\\s<>,\\w])*>\\s*))?(::)", + "captures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution" + } + ] + }, + "2": { + "name": "entity.name.namespace.scope-resolution.objcpp" + }, + "3": { + "patterns": [ + { + "include": "#template_call_innards" + } + ] + }, + "4": { + "name": "punctuation.separator.namespace.access.objcpp" + } + }, + "name": "meta.scope-resolution.objcpp" + }, + "angle_brackets": { + "begin": "<", + "end": ">", + "name": "meta.angle-brackets.objcpp", + "patterns": [ + { + "include": "#angle_brackets" + }, + { + "include": "$base" + } + ] + }, + "block": { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objcpp" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.bracket.curly.objcpp" + } + }, + "name": "meta.block.objcpp", + "patterns": [ + { + "captures": { + "1": { + "name": "support.function.any-method.objcpp" + }, + "2": { + "name": "punctuation.definition.parameters.objcpp" + } + }, + "match": "(?x)\n(\n (?!while|for|do|if|else|switch|catch|return)\n (?:\\b[A-Za-z_][A-Za-z0-9_]*+\\b|::)*+ # actual name\n)\n\\s*(\\() # opening bracket", + "name": "meta.function-call.objcpp" + }, + { + "include": "$base" + } + ] + }, + "constructor": { + "patterns": [ + { + "begin": "(?x)\n(?:^\\s*) # beginning of line\n((?!while|for|do|if|else|switch|catch)[A-Za-z_][A-Za-z0-9_:]*) # actual name\n\\s*(\\() # opening bracket", + "beginCaptures": { + "1": { + "name": "entity.name.function.constructor.objcpp" + }, + "2": { + "name": "punctuation.definition.parameters.begin.constructor.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.constructor.objcpp" + } + }, + "name": "meta.function.constructor.objcpp", + "patterns": [ + { + "include": "#probably_a_parameter" + }, + { + "include": "#function-innards-c" + } + ] + }, + { + "begin": "(?x)\n(:)\n(\n (?=\n \\s*[A-Za-z_][A-Za-z0-9_:]* # actual name\n \\s* (\\() # opening bracket\n )\n)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.initializer-list.parameters.objcpp" + } + }, + "end": "(?=\\{)", + "name": "meta.function.constructor.initializer-list.objcpp", + "patterns": [ + { + "include": "$base" + } + ] + } + ] + }, + "special_block": { + "patterns": [ + { + "comment": "https://en.cppreference.com/w/cpp/language/namespace", + "begin": "\\b(using)\\s+(namespace)\\s+(?:((?:[a-zA-Z_]\\w*\\s*(?:(?:<(?:[\\s<>,\\w])*>\\s*))?::)*)\\s*)?((?,\\w])*>\\s*))?::)*[a-zA-Z_]\\w*)|(?={)))", + "beginCaptures": { + "1": { + "name": "keyword.other.namespace.definition.objcpp storage.type.namespace.definition.objcpp" + }, + "2": { + "patterns": [ + { + "match": "(?-mix:(?|\\[|\\]|=))", + "name": "meta.namespace-block.objcpp", + "patterns": [ + { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.scope.objcpp" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.scope.objcpp" + } + }, + "patterns": [ + { + "include": "#special_block" + }, + { + "include": "#constructor" + }, + { + "include": "$base" + } + ] + }, + { + "include": "$base" + } + ] + }, + { + "begin": "\\b(?:(class)|(struct))\\b\\s*([_A-Za-z][_A-Za-z0-9]*\\b)?+(\\s*:\\s*(public|protected|private)\\s*([_A-Za-z][_A-Za-z0-9]*\\b)((\\s*,\\s*(public|protected|private)\\s*[_A-Za-z][_A-Za-z0-9]*\\b)*))?", + "beginCaptures": { + "1": { + "name": "storage.type.class.objcpp" + }, + "2": { + "name": "storage.type.struct.objcpp" + }, + "3": { + "name": "entity.name.type.objcpp" + }, + "5": { + "name": "storage.type.modifier.access.objcpp" + }, + "6": { + "name": "entity.name.type.inherited.objcpp" + }, + "7": { + "patterns": [ + { + "match": "(public|protected|private)", + "name": "storage.type.modifier.access.objcpp" + }, + { + "match": "[_A-Za-z][_A-Za-z0-9]*", + "name": "entity.name.type.inherited.objcpp" + } + ] + } + }, + "end": "(?<=\\})|(;)|(?=(\\(|\\)|>|\\[|\\]|=))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.statement.objcpp" + } + }, + "name": "meta.class-struct-block.objcpp", + "patterns": [ + { + "include": "#angle_brackets" + }, + { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objcpp" + } + }, + "end": "(\\})(\\s*\\n)?", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.objcpp" + }, + "2": { + "name": "invalid.illegal.you-forgot-semicolon.objcpp" + } + }, + "patterns": [ + { + "include": "#special_block" + }, + { + "include": "#constructor" + }, + { + "include": "$base" + } + ] + }, + { + "include": "$base" + } + ] + }, + { + "begin": "\\b(extern)(?=\\s*\")", + "beginCaptures": { + "1": { + "name": "storage.modifier.objcpp" + } + }, + "end": "(?<=\\})|(?=\\w)|(?=\\s*#\\s*endif\\b)", + "name": "meta.extern-block.objcpp", + "patterns": [ + { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objcpp" + } + }, + "end": "\\}|(?=\\s*#\\s*endif\\b)", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.bracket.curly.objcpp" + } + }, + "patterns": [ + { + "include": "#special_block" + }, + { + "include": "$base" + } + ] + }, + { + "include": "$base" + } + ] + } + ] + }, + "strings": { + "patterns": [ + { + "begin": "(u|u8|U|L)?\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.objcpp" + }, + "1": { + "name": "meta.encoding.objcpp" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objcpp" + } + }, + "name": "string.quoted.double.objcpp", + "patterns": [ + { + "match": "\\\\u\\h{4}|\\\\U\\h{8}", + "name": "constant.character.escape.objcpp" + }, + { + "match": "\\\\['\"?\\\\abfnrtv]", + "name": "constant.character.escape.objcpp" + }, + { + "match": "\\\\[0-7]{1,3}", + "name": "constant.character.escape.objcpp" + }, + { + "match": "\\\\x\\h+", + "name": "constant.character.escape.objcpp" + }, + { + "include": "#string_placeholder-c" + } + ] + }, + { + "begin": "(u|u8|U|L)?R\"(?:([^ ()\\\\\\t]{0,16})|([^ ()\\\\\\t]*))\\(", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.objcpp" + }, + "1": { + "name": "meta.encoding.objcpp" + }, + "3": { + "name": "invalid.illegal.delimiter-too-long.objcpp" + } + }, + "end": "\\)\\2(\\3)\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objcpp" + }, + "1": { + "name": "invalid.illegal.delimiter-too-long.objcpp" + } + }, + "name": "string.quoted.double.raw.objcpp" + } + ] + }, + "probably_a_parameter": { + "match": "(?:(?:([a-zA-Z_]\\w*)\\s*(?==)|(?<=\\w\\s|\\*\\/|[&*>\\]\\)])\\s*([a-zA-Z_]\\w*)\\s*(?=(?:\\[\\]\\s*)?(?:(?:,|\\))))))", + "captures": { + "1": { + "name": "variable.parameter.probably.defaulted.objcpp" + }, + "2": { + "name": "variable.parameter.probably.objcpp" + } + } + }, + "operator_overload": { + "begin": "((?:[a-zA-Z_]\\w*\\s*(?:(?:<(?:[\\s<>,\\w])*>\\s*))?::)*)\\s*(operator)((?:(?:\\s*(?:\\+\\+|\\-\\-|\\(\\)|\\[\\]|\\->|\\+\\+|\\-\\-|\\+|\\-|!|~|\\*|&|\\->\\*|\\*|\\/|%|\\+|\\-|<<|>>|<=>|<|<=|>|>=|==|!=|&|\\^|\\||&&|\\|\\||=|\\+=|\\-=|\\*=|\\/=|%=|<<=|>>=|&=|\\^=|\\|=|,)|\\s+(?:(?:(?:new|new\\[\\]|delete|delete\\[\\])|(?:[a-zA-Z_]\\w*\\s*(?:(?:<(?:[\\s<>,\\w])*>\\s*))?::)*[a-zA-Z_]\\w*\\s*(?:&)?)))))\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.scope.objcpp" + }, + "2": { + "name": "keyword.other.operator.overload.objcpp" + }, + "3": { + "name": "entity.name.operator.overloadee.objcpp" + }, + "4": { + "name": "punctuation.section.parameters.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parameters.end.bracket.round.objcpp" + } + }, + "name": "meta.function.definition.parameters.operator-overload.objcpp", + "patterns": [ + { + "include": "#probably_a_parameter" + }, + { + "include": "#function-innards-c" + } + ] + }, + "access-method": { + "name": "meta.function-call.member.objcpp", + "begin": "([a-zA-Z_][a-zA-Z_0-9]*|(?<=[\\]\\)]))\\s*(?:(\\.)|(->))((?:(?:[a-zA-Z_][a-zA-Z_0-9]*)\\s*(?:(?:\\.)|(?:->)))*)\\s*([a-zA-Z_][a-zA-Z_0-9]*)(\\()", + "beginCaptures": { + "1": { + "name": "variable.other.object.objcpp" + }, + "2": { + "name": "punctuation.separator.dot-access.objcpp" + }, + "3": { + "name": "punctuation.separator.pointer-access.objcpp" + }, + "4": { + "patterns": [ + { + "match": "\\.", + "name": "punctuation.separator.dot-access.objcpp" + }, + { + "match": "->", + "name": "punctuation.separator.pointer-access.objcpp" + }, + { + "match": "[a-zA-Z_][a-zA-Z_0-9]*", + "name": "variable.other.object.objcpp" + }, + { + "name": "everything.else.objcpp", + "match": ".+" + } + ] + }, + "5": { + "name": "entity.name.function.member.objcpp" + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.function.member.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.arguments.end.bracket.round.function.member.objcpp" + } + }, + "patterns": [ + { + "include": "#function-call-innards-c" + } + ] + }, + "access-member": { + "name": "variable.other.object.access.objcpp", + "match": "(?:(?:([a-zA-Z_]\\w*)|(?<=\\]|\\))))\\s*(?:(?:((?:(?:\\.|\\.\\*)))|((?:(?:->|->\\*)))))\\s*((?:[a-zA-Z_]\\w*\\s*(?:(?:\\.|->))\\s*)*)\\b(?!(?:auto|void|char|short|int|signed|unsigned|long|float|double|bool|wchar_t|u_char|u_short|u_int|u_long|ushort|uint|u_quad_t|quad_t|qaddr_t|caddr_t|daddr_t|div_t|dev_t|fixpt_t|blkcnt_t|blksize_t|gid_t|in_addr_t|in_port_t|ino_t|key_t|mode_t|nlink_t|id_t|pid_t|off_t|segsz_t|swblk_t|uid_t|id_t|clock_t|size_t|ssize_t|time_t|useconds_t|suseconds_t|pthread_attr_t|pthread_cond_t|pthread_condattr_t|pthread_mutex_t|pthread_mutexattr_t|pthread_once_t|pthread_rwlock_t|pthread_rwlockattr_t|pthread_t|pthread_key_t|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|int_least8_t|int_least16_t|int_least32_t|int_least64_t|uint_least8_t|uint_least16_t|uint_least32_t|uint_least64_t|int_fast8_t|int_fast16_t|int_fast32_t|int_fast64_t|uint_fast8_t|uint_fast16_t|uint_fast32_t|uint_fast64_t|intptr_t|uintptr_t|intmax_t|intmax_t|uintmax_t|uintmax_t))([a-zA-Z_]\\w*)\\b(?!\\()", + "captures": { + "1": { + "name": "variable.other.object.objcpp" + }, + "2": { + "name": "punctuation.separator.dot-access.objcpp" + }, + "3": { + "name": "punctuation.separator.pointer-access.objcpp" + }, + "4": { + "patterns": [ + { + "match": "\\.", + "name": "punctuation.separator.dot-access.objcpp" + }, + { + "match": "->", + "name": "punctuation.separator.pointer-access.objcpp" + }, + { + "match": "[a-zA-Z_]\\w*", + "name": "variable.other.object.objcpp" + }, + { + "match": ".+", + "name": "everything.else.objcpp" + } + ] + }, + "5": { + "name": "variable.other.member.objcpp" + } + } + }, + "block-c": { + "patterns": [ + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objcpp" + } + }, + "end": "}|(?=\\s*#\\s*(?:elif|else|endif)\\b)", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.bracket.curly.objcpp" + } + }, + "name": "meta.block.objcpp", + "patterns": [ + { + "include": "#block_innards-c" + } + ] + } + ] + }, + "block_innards-c": { + "patterns": [ + { + "include": "#preprocessor-rule-enabled-block" + }, + { + "include": "#preprocessor-rule-disabled-block" + }, + { + "include": "#preprocessor-rule-conditional-block" + }, + { + "include": "#access-method" + }, + { + "include": "#access-member" + }, + { + "include": "#c_function_call" + }, + { + "name": "meta.initialization.objcpp", + "begin": "(?x)\n(?:\n (?:\n\t(?=\\s)(?=+!]+ | \\(\\) | \\[\\]))\n)\n\\s*(\\() # opening bracket", + "beginCaptures": { + "1": { + "name": "variable.other.objcpp" + }, + "2": { + "name": "punctuation.section.parens.begin.bracket.round.initialization.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.initialization.objcpp" + } + }, + "patterns": [ + { + "include": "#function-call-innards-c" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objcpp" + } + }, + "end": "}|(?=\\s*#\\s*(?:elif|else|endif)\\b)", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.bracket.curly.objcpp" + } + }, + "patterns": [ + { + "include": "#block_innards-c" + } + ] + }, + { + "include": "#parens-block-c" + }, + { + "include": "$base" + } + ] + }, + "c_function_call": { + "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|return|typeid|alignof|alignas|sizeof|and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas)\\s*\\()\n(?=\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++\\s*(?:(?:<(?:[\\s<>,\\w])*>\\s*))?\\( # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", + "end": "(?<=\\))(?!\\w)", + "name": "meta.function-call.objcpp", + "patterns": [ + { + "include": "#function-call-innards-c" + } + ] + }, + "comments-c": { + "patterns": [ + { + "captures": { + "1": { + "name": "meta.toc-list.banner.block.objcpp" + } + }, + "match": "^/\\* =(\\s*.*?)\\s*= \\*/$\\n?", + "name": "comment.block.objcpp" + }, + { + "begin": "/\\*", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.begin.objcpp" + } + }, + "end": "\\*/", + "endCaptures": { + "0": { + "name": "punctuation.definition.comment.end.objcpp" + } + }, + "name": "comment.block.objcpp" + }, + { + "captures": { + "1": { + "name": "meta.toc-list.banner.line.objcpp" + } + }, + "match": "^// =(\\s*.*?)\\s*=\\s*$\\n?", + "name": "comment.line.banner.objcpp" + }, + { + "begin": "(^[ \\t]+)?(?=//)", + "beginCaptures": { + "1": { + "name": "punctuation.whitespace.comment.leading.objcpp" + } + }, + "end": "(?!\\G)", + "patterns": [ + { + "begin": "//", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.objcpp" + } + }, + "end": "(?=\\n)", + "name": "comment.line.double-slash.objcpp", + "patterns": [ + { + "include": "#line_continuation_character" + } + ] + } + ] + } + ] + }, + "disabled": { + "begin": "^\\s*#\\s*if(n?def)?\\b.*$", + "end": "^\\s*#\\s*endif\\b", + "patterns": [ + { + "include": "#disabled" + }, + { + "include": "#pragma-mark" + } + ] + }, + "line_continuation_character": { + "patterns": [ + { + "match": "(\\\\)\\n", + "captures": { + "1": { + "name": "constant.character.escape.line-continuation.objcpp" + } + } + } + ] + }, + "parens-c": { + "name": "punctuation.section.parens-c\b.objcpp", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + "parens-block-c": { + "name": "meta.block.parens.objcpp", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "#block_innards-c" + }, + { + "match": "(?>=|\\|=", + "name": "keyword.operator.assignment.compound.bitwise.objcpp" + }, + { + "match": "<<|>>", + "name": "keyword.operator.bitwise.shift.objcpp" + }, + { + "match": "!=|<=|>=|==|<|>", + "name": "keyword.operator.comparison.objcpp" + }, + { + "match": "&&|!|\\|\\|", + "name": "keyword.operator.logical.objcpp" + }, + { + "match": "&|\\||\\^|~", + "name": "keyword.operator.objcpp" + }, + { + "match": "=", + "name": "keyword.operator.assignment.objcpp" + }, + { + "match": "%|\\*|/|-|\\+", + "name": "keyword.operator.objcpp" + }, + { + "begin": "\\?", + "beginCaptures": { + "0": { + "name": "keyword.operator.ternary.objcpp" + } + }, + "end": ":", + "applyEndPatternLast": true, + "endCaptures": { + "0": { + "name": "keyword.operator.ternary.objcpp" + } + }, + "patterns": [ + { + "include": "#access-method" + }, + { + "include": "#access-member" + }, + { + "include": "#c_function_call" + }, + { + "include": "$base" + } + ] + } + ] + }, + "strings-c": { + "patterns": [ + { + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.objcpp" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objcpp" + } + }, + "name": "string.quoted.double.objcpp", + "patterns": [ + { + "include": "#string_escaped_char-c" + }, + { + "include": "#string_placeholder-c" + }, + { + "include": "#line_continuation_character" + } + ] + }, + { + "begin": "(?-mix:(?=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", + "end": "(?<=\\))(?!\\w)|(?=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.objcpp" + }, + "2": { + "name": "punctuation.section.arguments.begin.bracket.round.objcpp" + } + }, + "end": "(\\))|(?=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.objcpp" + }, + "2": { + "name": "punctuation.section.parameters.begin.bracket.round.objcpp" + } + }, + "end": "\\)|:", + "endCaptures": { + "0": { + "name": "punctuation.section.parameters.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "#probably_a_parameter" + }, + { + "include": "#function-innards-c" + } + ] + }, + { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "#function-innards-c" + } + ] + }, + { + "include": "$base" + } + ] + }, + "function-call-innards-c": { + "patterns": [ + { + "include": "#comments-c" + }, + { + "include": "#storage_types_c" + }, + { + "include": "#access-method" + }, + { + "include": "#access-member" + }, + { + "include": "#operators" + }, + { + "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|return|typeid|alignof|alignas|sizeof|and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas)\\s*\\()\n(\n(?:new)\\s*((?:(?:<(?:[\\s<>,\\w])*>\\s*))?) # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "beginCaptures": { + "1": { + "name": "keyword.operator.memory.new.objcpp" + }, + "2": { + "patterns": [ + { + "include": "#template_call_innards" + } + ] + }, + "3": { + "name": "punctuation.section.arguments.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.arguments.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "#function-call-innards-c" + } + ] + }, + { + "begin": "(?,\\w])*>\\s*))?::)*)\\s*([a-zA-Z_]\\w*)\\s*(?:((?:<(?:[\\s<>,\\w])*>\\s*)))?(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#scope_resolution" + } + ] + }, + "2": { + "name": "entity.name.function.call.objcpp" + }, + "3": { + "patterns": [ + { + "include": "#template_call_innards" + } + ] + }, + "4": { + "name": "punctuation.section.arguments.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.arguments.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "#function-call-innards-c" + } + ] + }, + { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objcpp" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objcpp" + } + }, + "patterns": [ + { + "include": "#function-call-innards-c" + } + ] + }, + { + "include": "#block_innards-c" + } + ] + } + } + }, + "string_escaped_char": { + "patterns": [ + { + "match": "(?x)\\\\ (\n\\\\\t\t\t |\n[abefnprtv'\"?] |\n[0-3]\\d{,2}\t |\n[4-7]\\d?\t\t|\nx[a-fA-F0-9]{,2} |\nu[a-fA-F0-9]{,4} |\nU[a-fA-F0-9]{,8} )", + "name": "constant.character.escape.objcpp" + }, + { + "match": "\\\\.", + "name": "invalid.illegal.unknown-escape.objcpp" + } + ] + }, + "string_placeholder": { + "patterns": [ + { + "match": "(?x) %\n(\\d+\\$)?\t\t\t\t\t\t # field (argument #)\n[#0\\- +']*\t\t\t\t\t\t # flags\n[,;:_]?\t\t\t\t\t\t\t # separator character (AltiVec)\n((-?\\d+)|\\*(-?\\d+\\$)?)?\t\t # minimum field width\n(\\.((-?\\d+)|\\*(-?\\d+\\$)?)?)?\t# precision\n(hh|h|ll|l|j|t|z|q|L|vh|vl|v|hv|hl)? # length modifier\n[diouxXDOUeEfFgGaACcSspn%]\t\t # conversion type", + "name": "constant.other.placeholder.objcpp" + }, + { + "match": "(%)(?!\"\\s*(PRI|SCN))", + "captures": { + "1": { + "name": "invalid.illegal.placeholder.objcpp" + } + } + } + ] + }, + "bracketed_content": { + "begin": "\\[", + "beginCaptures": { + "0": { + "name": "punctuation.section.scope.begin.objcpp" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "punctuation.section.scope.end.objcpp" + } + }, + "name": "meta.bracketed.objcpp", + "patterns": [ + { + "begin": "(?=predicateWithFormat:)(?<=NSPredicate )(predicateWithFormat:)", + "beginCaptures": { + "1": { + "name": "support.function.any-method.objcpp" + }, + "2": { + "name": "punctuation.separator.arguments.objcpp" + } + }, + "end": "(?=\\])", + "name": "meta.function-call.predicate.objcpp", + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.separator.arguments.objcpp" + } + }, + "match": "\\bargument(Array|s)(:)", + "name": "support.function.any-method.name-of-parameter.objcpp" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.arguments.objcpp" + } + }, + "match": "\\b\\w+(:)", + "name": "invalid.illegal.unknown-method.objcpp" + }, + { + "begin": "@\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.objcpp" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objcpp" + } + }, + "name": "string.quoted.double.objcpp", + "patterns": [ + { + "match": "\\b(AND|OR|NOT|IN)\\b", + "name": "keyword.operator.logical.predicate.cocoa.objcpp" + }, + { + "match": "\\b(ALL|ANY|SOME|NONE)\\b", + "name": "constant.language.predicate.cocoa.objcpp" + }, + { + "match": "\\b(NULL|NIL|SELF|TRUE|YES|FALSE|NO|FIRST|LAST|SIZE)\\b", + "name": "constant.language.predicate.cocoa.objcpp" + }, + { + "match": "\\b(MATCHES|CONTAINS|BEGINSWITH|ENDSWITH|BETWEEN)\\b", + "name": "keyword.operator.comparison.predicate.cocoa.objcpp" + }, + { + "match": "\\bC(ASEINSENSITIVE|I)\\b", + "name": "keyword.other.modifier.predicate.cocoa.objcpp" + }, + { + "match": "\\b(ANYKEY|SUBQUERY|CAST|TRUEPREDICATE|FALSEPREDICATE)\\b", + "name": "keyword.other.predicate.cocoa.objcpp" + }, + { + "match": "\\\\(\\\\|[abefnrtv'\"?]|[0-3]\\d{,2}|[4-7]\\d?|x[a-zA-Z0-9]+)", + "name": "constant.character.escape.objcpp" + }, + { + "match": "\\\\.", + "name": "invalid.illegal.unknown-escape.objcpp" + } + ] + }, + { + "include": "#special_variables" + }, + { + "include": "#c_functions" + }, + { + "include": "$base" + } + ] + }, + { + "begin": "(?=\\w)(?<=[\\w\\])\"] )(\\w+(?:(:)|(?=\\])))", + "beginCaptures": { + "1": { + "name": "support.function.any-method.objcpp" + }, + "2": { + "name": "punctuation.separator.arguments.objcpp" + } + }, + "end": "(?=\\])", + "name": "meta.function-call.objcpp", + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.separator.arguments.objcpp" + } + }, + "match": "\\b\\w+(:)", + "name": "support.function.any-method.name-of-parameter.objcpp" + }, + { + "include": "#special_variables" + }, + { + "include": "#c_functions" + }, + { + "include": "$base" + } + ] + }, + { + "include": "#special_variables" + }, + { + "include": "#c_functions" + }, + { + "include": "$self" + } + ] + }, + "c_functions": { + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.whitespace.support.function.leading.objcpp" + }, + "2": { + "name": "support.function.C99.objcpp" + } + }, + "match": "(\\s*)\\b(hypot(f|l)?|s(scanf|ystem|nprintf|ca(nf|lb(n(f|l)?|ln(f|l)?))|i(n(h(f|l)?|f|l)?|gn(al|bit))|tr(s(tr|pn)|nc(py|at|mp)|c(spn|hr|oll|py|at|mp)|to(imax|d|u(l(l)?|max)|k|f|l(d|l)?)|error|pbrk|ftime|len|rchr|xfrm)|printf|et(jmp|vbuf|locale|buf)|qrt(f|l)?|w(scanf|printf)|rand)|n(e(arbyint(f|l)?|xt(toward(f|l)?|after(f|l)?))|an(f|l)?)|c(s(in(h(f|l)?|f|l)?|qrt(f|l)?)|cos(h(f)?|f|l)?|imag(f|l)?|t(ime|an(h(f|l)?|f|l)?)|o(s(h(f|l)?|f|l)?|nj(f|l)?|pysign(f|l)?)|p(ow(f|l)?|roj(f|l)?)|e(il(f|l)?|xp(f|l)?)|l(o(ck|g(f|l)?)|earerr)|a(sin(h(f|l)?|f|l)?|cos(h(f|l)?|f|l)?|tan(h(f|l)?|f|l)?|lloc|rg(f|l)?|bs(f|l)?)|real(f|l)?|brt(f|l)?)|t(ime|o(upper|lower)|an(h(f|l)?|f|l)?|runc(f|l)?|gamma(f|l)?|mp(nam|file))|i(s(space|n(ormal|an)|cntrl|inf|digit|u(nordered|pper)|p(unct|rint)|finite|w(space|c(ntrl|type)|digit|upper|p(unct|rint)|lower|al(num|pha)|graph|xdigit|blank)|l(ower|ess(equal|greater)?)|al(num|pha)|gr(eater(equal)?|aph)|xdigit|blank)|logb(f|l)?|max(div|abs))|di(v|fftime)|_Exit|unget(c|wc)|p(ow(f|l)?|ut(s|c(har)?|wc(har)?)|error|rintf)|e(rf(c(f|l)?|f|l)?|x(it|p(2(f|l)?|f|l|m1(f|l)?)?))|v(s(scanf|nprintf|canf|printf|w(scanf|printf))|printf|f(scanf|printf|w(scanf|printf))|w(scanf|printf)|a_(start|copy|end|arg))|qsort|f(s(canf|e(tpos|ek))|close|tell|open|dim(f|l)?|p(classify|ut(s|c|w(s|c))|rintf)|e(holdexcept|set(e(nv|xceptflag)|round)|clearexcept|testexcept|of|updateenv|r(aiseexcept|ror)|get(e(nv|xceptflag)|round))|flush|w(scanf|ide|printf|rite)|loor(f|l)?|abs(f|l)?|get(s|c|pos|w(s|c))|re(open|e|ad|xp(f|l)?)|m(in(f|l)?|od(f|l)?|a(f|l|x(f|l)?)?))|l(d(iv|exp(f|l)?)|o(ngjmp|cal(time|econv)|g(1(p(f|l)?|0(f|l)?)|2(f|l)?|f|l|b(f|l)?)?)|abs|l(div|abs|r(int(f|l)?|ound(f|l)?))|r(int(f|l)?|ound(f|l)?)|gamma(f|l)?)|w(scanf|c(s(s(tr|pn)|nc(py|at|mp)|c(spn|hr|oll|py|at|mp)|to(imax|d|u(l(l)?|max)|k|f|l(d|l)?|mbs)|pbrk|ftime|len|r(chr|tombs)|xfrm)|to(b|mb)|rtomb)|printf|mem(set|c(hr|py|mp)|move))|a(s(sert|ctime|in(h(f|l)?|f|l)?)|cos(h(f|l)?|f|l)?|t(o(i|f|l(l)?)|exit|an(h(f|l)?|2(f|l)?|f|l)?)|b(s|ort))|g(et(s|c(har)?|env|wc(har)?)|mtime)|r(int(f|l)?|ound(f|l)?|e(name|alloc|wind|m(ove|quo(f|l)?|ainder(f|l)?))|a(nd|ise))|b(search|towc)|m(odf(f|l)?|em(set|c(hr|py|mp)|move)|ktime|alloc|b(s(init|towcs|rtowcs)|towc|len|r(towc|len))))\\b" + }, + { + "captures": { + "1": { + "name": "punctuation.whitespace.function-call.leading.objcpp" + }, + "2": { + "name": "support.function.any-method.objcpp" + }, + "3": { + "name": "punctuation.definition.parameters.objcpp" + } + }, + "match": "(?x) (?: (?= \\s ) (?:(?<=else|new|return) | (?\\\\\\s*\\n)", + "name": "punctuation.separator.continuation.objcpp" + } + ] + } + ] + } + ] + }, + "disabled": { + "begin": "^\\s*#\\s*if(n?def)?\\b.*$", + "comment": "eat nested preprocessor if(def)s", + "end": "^\\s*#\\s*endif\\b.*$", + "patterns": [ + { + "include": "#disabled" + }, + { + "include": "#pragma-mark" + } + ] + }, + "implementation_innards": { + "patterns": [ + { + "include": "#preprocessor-rule-enabled-implementation" + }, + { + "include": "#preprocessor-rule-disabled-implementation" + }, + { + "include": "#preprocessor-rule-other-implementation" + }, + { + "include": "#property_directive" + }, + { + "include": "#special_variables" + }, + { + "include": "#method_super" + }, + { + "include": "$base" + } + ] + }, + "interface_innards": { + "patterns": [ + { + "include": "#preprocessor-rule-enabled-interface" + }, + { + "include": "#preprocessor-rule-disabled-interface" + }, + { + "include": "#preprocessor-rule-other-interface" + }, + { + "include": "#properties" + }, + { + "include": "#protocol_list" + }, + { + "include": "#method" + }, + { + "include": "$base" + } + ] + }, + "method": { + "begin": "^(-|\\+)\\s*", + "end": "(?=\\{|#)|;", + "name": "meta.function.objcpp", + "patterns": [ + { + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.definition.type.begin.objcpp" + } + }, + "end": "(\\))\\s*(\\w+\\b)", + "endCaptures": { + "1": { + "name": "punctuation.definition.type.end.objcpp" + }, + "2": { + "name": "entity.name.function.objcpp" + } + }, + "name": "meta.return-type.objcpp", + "patterns": [ + { + "include": "#protocol_list" + }, + { + "include": "#protocol_type_qualifier" + }, + { + "include": "$base" + } + ] + }, + { + "match": "\\b\\w+(?=:)", + "name": "entity.name.function.name-of-parameter.objcpp" + }, + { + "begin": "((:))\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.name-of-parameter.objcpp" + }, + "2": { + "name": "punctuation.separator.arguments.objcpp" + }, + "3": { + "name": "punctuation.definition.type.begin.objcpp" + } + }, + "end": "(\\))\\s*(\\w+\\b)?", + "endCaptures": { + "1": { + "name": "punctuation.definition.type.end.objcpp" + }, + "2": { + "name": "variable.parameter.function.objcpp" + } + }, + "name": "meta.argument-type.objcpp", + "patterns": [ + { + "include": "#protocol_list" + }, + { + "include": "#protocol_type_qualifier" + }, + { + "include": "$base" + } + ] + }, + { + "include": "#comment" + } + ] + }, + "method_super": { + "begin": "^(?=-|\\+)", + "end": "(?<=\\})|(?=#)", + "name": "meta.function-with-body.objcpp", + "patterns": [ + { + "include": "#method" + }, + { + "include": "$base" + } + ] + }, + "pragma-mark": { + "captures": { + "1": { + "name": "meta.preprocessor.objcpp" + }, + "2": { + "name": "keyword.control.import.pragma.objcpp" + }, + "3": { + "name": "meta.toc-list.pragma-mark.objcpp" + } + }, + "match": "^\\s*(#\\s*(pragma\\s+mark)\\s+(.*))", + "name": "meta.section.objcpp" + }, + "preprocessor-rule-disabled-implementation": { + "begin": "^\\s*(#(if)\\s+(0)\\b).*", + "captures": { + "1": { + "name": "meta.preprocessor.objcpp" + }, + "2": { + "name": "keyword.control.import.if.objcpp" + }, + "3": { + "name": "constant.numeric.preprocessor.objcpp" + } + }, + "end": "^\\s*(#\\s*(endif)\\b.*?(?:(?=(?://|/\\*))|$))", + "patterns": [ + { + "begin": "^\\s*(#\\s*(else)\\b)", + "captures": { + "1": { + "name": "meta.preprocessor.objcpp" + }, + "2": { + "name": "keyword.control.import.else.objcpp" + } + }, + "end": "(?=^\\s*#\\s*endif\\b.*?(?:(?=(?://|/\\*))|$))", + "patterns": [ + { + "include": "#interface_innards" + } + ] + }, + { + "begin": "", + "end": "(?=^\\s*#\\s*(else|endif)\\b.*?(?:(?=(?://|/\\*))|$))", + "name": "comment.block.preprocessor.if-branch.objcpp", + "patterns": [ + { + "include": "#disabled" + }, + { + "include": "#pragma-mark" + } + ] + } + ] + }, + "preprocessor-rule-disabled-interface": { + "begin": "^\\s*(#(if)\\s+(0)\\b).*", + "captures": { + "1": { + "name": "meta.preprocessor.objcpp" + }, + "2": { + "name": "keyword.control.import.if.objcpp" + }, + "3": { + "name": "constant.numeric.preprocessor.objcpp" + } + }, + "end": "^\\s*(#\\s*(endif)\\b.*?(?:(?=(?://|/\\*))|$))", + "patterns": [ + { + "begin": "^\\s*(#\\s*(else)\\b)", + "captures": { + "1": { + "name": "meta.preprocessor.objcpp" + }, + "2": { + "name": "keyword.control.import.else.objcpp" + } + }, + "end": "(?=^\\s*#\\s*endif\\b.*?(?:(?=(?://|/\\*))|$))", + "patterns": [ + { + "include": "#interface_innards" + } + ] + }, + { + "begin": "", + "end": "(?=^\\s*#\\s*(else|endif)\\b.*?(?:(?=(?://|/\\*))|$))", + "name": "comment.block.preprocessor.if-branch.objcpp", + "patterns": [ + { + "include": "#disabled" + }, + { + "include": "#pragma-mark" + } + ] + } + ] + }, + "preprocessor-rule-enabled-implementation": { + "begin": "^\\s*(#(if)\\s+(0*1)\\b)", + "captures": { + "1": { + "name": "meta.preprocessor.objcpp" + }, + "2": { + "name": "keyword.control.import.if.objcpp" + }, + "3": { + "name": "constant.numeric.preprocessor.objcpp" + } + }, + "end": "^\\s*(#\\s*(endif)\\b.*?(?:(?=(?://|/\\*))|$))", + "patterns": [ + { + "begin": "^\\s*(#\\s*(else)\\b).*", + "captures": { + "1": { + "name": "meta.preprocessor.objcpp" + }, + "2": { + "name": "keyword.control.import.else.objcpp" + } + }, + "contentName": "comment.block.preprocessor.else-branch.objcpp", + "end": "(?=^\\s*#\\s*endif\\b.*?(?:(?=(?://|/\\*))|$))", + "patterns": [ + { + "include": "#disabled" + }, + { + "include": "#pragma-mark" + } + ] + }, + { + "begin": "", + "end": "(?=^\\s*#\\s*(else|endif)\\b.*?(?:(?=(?://|/\\*))|$))", + "patterns": [ + { + "include": "#implementation_innards" + } + ] + } + ] + }, + "preprocessor-rule-enabled-interface": { + "begin": "^\\s*(#(if)\\s+(0*1)\\b)", + "captures": { + "1": { + "name": "meta.preprocessor.objcpp" + }, + "2": { + "name": "keyword.control.import.if.objcpp" + }, + "3": { + "name": "constant.numeric.preprocessor.objcpp" + } + }, + "end": "^\\s*(#\\s*(endif)\\b.*?(?:(?=(?://|/\\*))|$))", + "patterns": [ + { + "begin": "^\\s*(#\\s*(else)\\b).*", + "captures": { + "1": { + "name": "meta.preprocessor.objcpp" + }, + "2": { + "name": "keyword.control.import.else.objcpp" + } + }, + "contentName": "comment.block.preprocessor.else-branch.objcpp", + "end": "(?=^\\s*#\\s*endif\\b.*?(?:(?=(?://|/\\*))|$))", + "patterns": [ + { + "include": "#disabled" + }, + { + "include": "#pragma-mark" + } + ] + }, + { + "begin": "", + "end": "(?=^\\s*#\\s*(else|endif)\\b.*?(?:(?=(?://|/\\*))|$))", + "patterns": [ + { + "include": "#interface_innards" + } + ] + } + ] + }, + "preprocessor-rule-other-implementation": { + "begin": "^\\s*(#\\s*(if(n?def)?)\\b.*?(?:(?=(?://|/\\*))|$))", + "captures": { + "1": { + "name": "meta.preprocessor.objcpp" + }, + "2": { + "name": "keyword.control.import.objcpp" + } + }, + "end": "^\\s*(#\\s*(endif)\\b).*?(?:(?=(?://|/\\*))|$)", + "patterns": [ + { + "include": "#implementation_innards" + } + ] + }, + "preprocessor-rule-other-interface": { + "begin": "^\\s*(#\\s*(if(n?def)?)\\b.*?(?:(?=(?://|/\\*))|$))", + "captures": { + "1": { + "name": "meta.preprocessor.objcpp" + }, + "2": { + "name": "keyword.control.import.objcpp" + } + }, + "end": "^\\s*(#\\s*(endif)\\b).*?(?:(?=(?://|/\\*))|$)", + "patterns": [ + { + "include": "#interface_innards" + } + ] + }, + "properties": { + "patterns": [ + { + "begin": "((@)property)\\s*(\\()", + "beginCaptures": { + "1": { + "name": "keyword.other.property.objcpp" + }, + "2": { + "name": "punctuation.definition.keyword.objcpp" + }, + "3": { + "name": "punctuation.section.scope.begin.objcpp" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.scope.end.objcpp" + } + }, + "name": "meta.property-with-attributes.objcpp", + "patterns": [ + { + "match": "\\b(getter|setter|readonly|readwrite|assign|retain|copy|nonatomic|strong|weak)\\b", + "name": "keyword.other.property.attribute.objcpp" + } + ] + }, + { + "captures": { + "1": { + "name": "keyword.other.property.objcpp" + }, + "2": { + "name": "punctuation.definition.keyword.objcpp" + } + }, + "match": "((@)property)\\b", + "name": "meta.property.objcpp" + } + ] + }, + "property_directive": { + "captures": { + "1": { + "name": "punctuation.definition.keyword.objcpp" + } + }, + "match": "(@)(dynamic|synthesize)\\b", + "name": "keyword.other.property.directive.objcpp" + }, + "protocol_list": { + "begin": "(<)", + "beginCaptures": { + "1": { + "name": "punctuation.section.scope.begin.objcpp" + } + }, + "end": "(>)", + "endCaptures": { + "1": { + "name": "punctuation.section.scope.end.objcpp" + } + }, + "name": "meta.protocol-list.objcpp", + "patterns": [ + { + "match": "\\bNS(GlyphStorage|M(utableCopying|enuItem)|C(hangeSpelling|o(ding|pying|lorPicking(Custom|Default)))|T(oolbarItemValidations|ext(Input|AttachmentCell))|I(nputServ(iceProvider|erMouseTracker)|gnoreMisspelledWords)|Obj(CTypeSerializationCallBack|ect)|D(ecimalNumberBehaviors|raggingInfo)|U(serInterfaceValidations|RL(HandleClient|DownloadDelegate|ProtocolClient|AuthenticationChallengeSender))|Validated(ToobarItem|UserInterfaceItem)|Locking)\\b", + "name": "support.other.protocol.objcpp" + } + ] + }, + "protocol_type_qualifier": { + "match": "\\b(in|out|inout|oneway|bycopy|byref)\\b", + "name": "storage.modifier.protocol.objcpp" + }, + "special_variables": { + "patterns": [ + { + "match": "\\b_cmd\\b", + "name": "variable.other.selector.objcpp" + }, + { + "match": "\\b(self|super)\\b", + "name": "variable.language.objcpp" + } + ] + } + } } \ No newline at end of file diff --git a/extensions/objective-c/syntaxes/objective-c.tmLanguage.json b/extensions/objective-c/syntaxes/objective-c.tmLanguage.json index b88ebab9eb8..e08731bb134 100644 --- a/extensions/objective-c/syntaxes/objective-c.tmLanguage.json +++ b/extensions/objective-c/syntaxes/objective-c.tmLanguage.json @@ -1,10 +1,10 @@ { "information_for_contributors": [ - "This file has been converted from https://github.com/atom/language-objective-c/blob/master/grammars/objective-c.cson", + "This file has been converted from https://github.com/jeff-hykin/cpp-textmate-grammar/blob/master//syntaxes/objc.tmLanguage.json", "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/atom/language-objective-c/commit/0727e04544f3414c1c339cf15a39a05ea3938cb4", + "version": "https://github.com/jeff-hykin/cpp-textmate-grammar/commit/9c4f4b3291538d9f5144f02d3b6af877b84f2cb2", "name": "Objective-C", "scopeName": "source.objc", "patterns": [ @@ -83,14 +83,14 @@ "name": "string.quoted.double.objc", "patterns": [ { - "include": "source.c#string_escaped_char" + "include": "#string_escaped_char" }, { "match": "(?x)%\n\t\t\t\t\t\t(\\d+\\$)? # field (argument #)\n\t\t\t\t\t\t[#0\\- +']* # flags\n\t\t\t\t\t\t((-?\\d+)|\\*(-?\\d+\\$)?)? # minimum field width\n\t\t\t\t\t\t(\\.((-?\\d+)|\\*(-?\\d+\\$)?)?)? # precision\n\t\t\t\t\t\t[@] # conversion type\n\t\t\t\t\t", "name": "constant.other.placeholder.objc" }, { - "include": "source.c#string_placeholder" + "include": "#string_placeholder" } ] }, @@ -214,15 +214,15 @@ }, { "match": "\\bNSApp\\b", - "name": "support.variable.foundation" + "name": "support.variable.foundation.objc" }, { "captures": { "1": { - "name": "punctuation.whitespace.support.function.cocoa.leopard" + "name": "punctuation.whitespace.support.function.cocoa.leopard.objc" }, "2": { - "name": "support.function.cocoa.leopard" + "name": "support.function.cocoa.leopard.objc" } }, "match": "(\\s*)\\b(NS(Rect(ToCGRect|FromCGRect)|MakeCollectable|S(tringFromProtocol|ize(ToCGSize|FromCGSize))|Draw(NinePartImage|ThreePartImage)|P(oint(ToCGPoint|FromCGPoint)|rotocolFromString)|EventMaskFromType|Value))\\b" @@ -230,66 +230,2677 @@ { "captures": { "1": { - "name": "punctuation.whitespace.support.function.leading.cocoa" + "name": "punctuation.whitespace.support.function.leading.cocoa.objc" }, "2": { - "name": "support.function.cocoa" + "name": "support.function.cocoa.objc" } }, "match": "(\\s*)\\b(NS(R(ound(DownToMultipleOfPageSize|UpToMultipleOfPageSize)|un(CriticalAlertPanel(RelativeToWindow)?|InformationalAlertPanel(RelativeToWindow)?|AlertPanel(RelativeToWindow)?)|e(set(MapTable|HashTable)|c(ycleZone|t(Clip(List)?|F(ill(UsingOperation|List(UsingOperation|With(Grays|Colors(UsingOperation)?))?)?|romString))|ordAllocationEvent)|turnAddress|leaseAlertPanel|a(dPixel|l(MemoryAvailable|locateCollectable))|gisterServicesProvider)|angeFromString)|Get(SizeAndAlignment|CriticalAlertPanel|InformationalAlertPanel|UncaughtExceptionHandler|FileType(s)?|WindowServerMemory|AlertPanel)|M(i(n(X|Y)|d(X|Y))|ouseInRect|a(p(Remove|Get|Member|Insert(IfAbsent|KnownAbsent)?)|ke(R(ect|ange)|Size|Point)|x(Range|X|Y)))|B(itsPer(SampleFromDepth|PixelFromDepth)|e(stDepth|ep|gin(CriticalAlertSheet|InformationalAlertSheet|AlertSheet)))|S(ho(uldRetainWithZone|w(sServicesMenuItem|AnimationEffect))|tringFrom(R(ect|ange)|MapTable|S(ize|elector)|HashTable|Class|Point)|izeFromString|e(t(ShowsServicesMenuItem|ZoneName|UncaughtExceptionHandler|FocusRingStyle)|lectorFromString|archPathForDirectoriesInDomains)|wap(Big(ShortToHost|IntToHost|DoubleToHost|FloatToHost|Long(ToHost|LongToHost))|Short|Host(ShortTo(Big|Little)|IntTo(Big|Little)|DoubleTo(Big|Little)|FloatTo(Big|Little)|Long(To(Big|Little)|LongTo(Big|Little)))|Int|Double|Float|L(ittle(ShortToHost|IntToHost|DoubleToHost|FloatToHost|Long(ToHost|LongToHost))|ong(Long)?)))|H(ighlightRect|o(stByteOrder|meDirectory(ForUser)?)|eight|ash(Remove|Get|Insert(IfAbsent|KnownAbsent)?)|FSType(CodeFromFileType|OfFile))|N(umberOfColorComponents|ext(MapEnumeratorPair|HashEnumeratorItem))|C(o(n(tainsRect|vert(GlyphsToPackedGlyphs|Swapped(DoubleToHost|FloatToHost)|Host(DoubleToSwapped|FloatToSwapped)))|unt(MapTable|HashTable|Frames|Windows(ForContext)?)|py(M(emoryPages|apTableWithZone)|Bits|HashTableWithZone|Object)|lorSpaceFromDepth|mpare(MapTables|HashTables))|lassFromString|reate(MapTable(WithZone)?|HashTable(WithZone)?|Zone|File(namePboardType|ContentsPboardType)))|TemporaryDirectory|I(s(ControllerMarker|EmptyRect|FreedObject)|n(setRect|crementExtraRefCount|te(r(sect(sRect|ionR(ect|ange))|faceStyleForKey)|gralRect)))|Zone(Realloc|Malloc|Name|Calloc|Fr(omPointer|ee))|O(penStepRootDirectory|ffsetRect)|D(i(sableScreenUpdates|videRect)|ottedFrameRect|e(c(imal(Round|Multiply|S(tring|ubtract)|Normalize|Co(py|mpa(ct|re))|IsNotANumber|Divide|Power|Add)|rementExtraRefCountWasZero)|faultMallocZone|allocate(MemoryPages|Object))|raw(Gr(oove|ayBezel)|B(itmap|utton)|ColorTiledRects|TiledRects|DarkBezel|W(hiteBezel|indowBackground)|LightBezel))|U(serName|n(ionR(ect|ange)|registerServicesProvider)|pdateDynamicServices)|Java(Bundle(Setup|Cleanup)|Setup(VirtualMachine)?|Needs(ToLoadClasses|VirtualMachine)|ClassesF(orBundle|romPath)|ObjectNamedInPath|ProvidesClasses)|P(oint(InRect|FromString)|erformService|lanarFromDepth|ageSize)|E(n(d(MapTableEnumeration|HashTableEnumeration)|umerate(MapTable|HashTable)|ableScreenUpdates)|qual(R(ects|anges)|Sizes|Points)|raseRect|xtraRefCount)|F(ileTypeForHFSTypeCode|ullUserName|r(ee(MapTable|HashTable)|ame(Rect(WithWidth(UsingOperation)?)?|Address)))|Wi(ndowList(ForContext)?|dth)|Lo(cationInRange|g(v|PageSize)?)|A(ccessibility(R(oleDescription(ForUIElement)?|aiseBadArgumentException)|Unignored(Children(ForOnlyChild)?|Descendant|Ancestor)|PostNotification|ActionDescription)|pplication(Main|Load)|vailableWindowDepths|ll(MapTable(Values|Keys)|HashTableObjects|ocate(MemoryPages|Collectable|Object)))))\\b" }, { "match": "\\bNS(RuleEditor|G(arbageCollector|radient)|MapTable|HashTable|Co(ndition|llectionView(Item)?)|T(oolbarItemGroup|extInputClient|r(eeNode|ackingArea))|InvocationOperation|Operation(Queue)?|D(ictionaryController|ockTile)|P(ointer(Functions|Array)|athC(o(ntrol(Delegate)?|mponentCell)|ell(Delegate)?)|r(intPanelAccessorizing|edicateEditor(RowTemplate)?))|ViewController|FastEnumeration|Animat(ionContext|ablePropertyContainer))\\b", - "name": "support.class.cocoa.leopard" + "name": "support.class.cocoa.leopard.objc" }, { "match": "\\bNS(R(u(nLoop|ler(Marker|View))|e(sponder|cursiveLock|lativeSpecifier)|an(domSpecifier|geSpecifier))|G(etCommand|lyph(Generator|Storage|Info)|raphicsContext)|XML(Node|D(ocument|TD(Node)?)|Parser|Element)|M(iddleSpecifier|ov(ie(View)?|eCommand)|utable(S(tring|et)|C(haracterSet|opying)|IndexSet|D(ictionary|ata)|URLRequest|ParagraphStyle|A(ttributedString|rray))|e(ssagePort(NameServer)?|nu(Item(Cell)?|View)?|t(hodSignature|adata(Item|Query(ResultGroup|AttributeValueTuple)?)))|a(ch(BootstrapServer|Port)|trix))|B(itmapImageRep|ox|u(ndle|tton(Cell)?)|ezierPath|rowser(Cell)?)|S(hadow|c(anner|r(ipt(SuiteRegistry|C(o(ercionHandler|mmand(Description)?)|lassDescription)|ObjectSpecifier|ExecutionContext|WhoseTest)|oll(er|View)|een))|t(epper(Cell)?|atus(Bar|Item)|r(ing|eam))|imple(HorizontalTypesetter|CString)|o(cketPort(NameServer)?|und|rtDescriptor)|p(e(cifierTest|ech(Recognizer|Synthesizer)|ll(Server|Checker))|litView)|e(cureTextField(Cell)?|t(Command)?|archField(Cell)?|rializer|gmentedC(ontrol|ell))|lider(Cell)?|avePanel)|H(ost|TTP(Cookie(Storage)?|URLResponse)|elpManager)|N(ib(Con(nector|trolConnector)|OutletConnector)?|otification(Center|Queue)?|u(ll|mber(Formatter)?)|etService(Browser)?|ameSpecifier)|C(ha(ngeSpelling|racterSet)|o(n(stantString|nection|trol(ler)?|ditionLock)|d(ing|er)|unt(Command|edSet)|pying|lor(Space|P(ick(ing(Custom|Default)|er)|anel)|Well|List)?|m(p(oundPredicate|arisonPredicate)|boBox(Cell)?))|u(stomImageRep|rsor)|IImageRep|ell|l(ipView|o(seCommand|neCommand)|assDescription)|a(ched(ImageRep|URLResponse)|lendar(Date)?)|reateCommand)|T(hread|ypesetter|ime(Zone|r)|o(olbar(Item(Validations)?)?|kenField(Cell)?)|ext(Block|Storage|Container|Tab(le(Block)?)?|Input|View|Field(Cell)?|List|Attachment(Cell)?)?|a(sk|b(le(Header(Cell|View)|Column|View)|View(Item)?))|reeController)|I(n(dex(S(pecifier|et)|Path)|put(Manager|S(tream|erv(iceProvider|er(MouseTracker)?)))|vocation)|gnoreMisspelledWords|mage(Rep|Cell|View)?)|O(ut(putStream|lineView)|pen(GL(Context|Pixel(Buffer|Format)|View)|Panel)|bj(CTypeSerializationCallBack|ect(Controller)?))|D(i(st(antObject(Request)?|ributed(NotificationCenter|Lock))|ctionary|rectoryEnumerator)|ocument(Controller)?|e(serializer|cimalNumber(Behaviors|Handler)?|leteCommand)|at(e(Components|Picker(Cell)?|Formatter)?|a)|ra(wer|ggingInfo))|U(ser(InterfaceValidations|Defaults(Controller)?)|RL(Re(sponse|quest)|Handle(Client)?|C(onnection|ache|redential(Storage)?)|Download(Delegate)?|Prot(ocol(Client)?|ectionSpace)|AuthenticationChallenge(Sender)?)?|n(iqueIDSpecifier|doManager|archiver))|P(ipe|o(sitionalSpecifier|pUpButton(Cell)?|rt(Message|NameServer|Coder)?)|ICTImageRep|ersistentDocument|DFImageRep|a(steboard|nel|ragraphStyle|geLayout)|r(int(Info|er|Operation|Panel)|o(cessInfo|tocolChecker|perty(Specifier|ListSerialization)|gressIndicator|xy)|edicate))|E(numerator|vent|PSImageRep|rror|x(ception|istsCommand|pression))|V(iew(Animation)?|al(idated(ToobarItem|UserInterfaceItem)|ue(Transformer)?))|Keyed(Unarchiver|Archiver)|Qui(ckDrawView|tCommand)|F(ile(Manager|Handle|Wrapper)|o(nt(Manager|Descriptor|Panel)?|rm(Cell|atter)))|W(hoseSpecifier|indow(Controller)?|orkspace)|L(o(c(k(ing)?|ale)|gicalTest)|evelIndicator(Cell)?|ayoutManager)|A(ssertionHandler|nimation|ctionCell|ttributedString|utoreleasePool|TSTypesetter|ppl(ication|e(Script|Event(Manager|Descriptor)))|ffineTransform|lert|r(chiver|ray(Controller)?)))\\b", - "name": "support.class.cocoa" + "name": "support.class.cocoa.objc" }, { "match": "\\bNS(R(oundingMode|ule(Editor(RowType|NestingMode)|rOrientation)|e(questUserAttentionType|lativePosition))|G(lyphInscription|radientDrawingOptions)|XML(NodeKind|D(ocumentContentKind|TDNodeKind)|ParserError)|M(ultibyteGlyphPacking|apTableOptions)|B(itmapFormat|oxType|ezierPathElement|ackgroundStyle|rowserDropOperation)|S(tr(ing(CompareOptions|DrawingOptions|EncodingConversionOptions)|eam(Status|Event))|p(eechBoundary|litViewDividerStyle)|e(archPathD(irectory|omainMask)|gmentS(tyle|witchTracking))|liderType|aveOptions)|H(TTPCookieAcceptPolicy|ashTableOptions)|N(otification(SuspensionBehavior|Coalescing)|umberFormatter(RoundingMode|Behavior|Style|PadPosition)|etService(sError|Options))|C(haracterCollection|o(lor(RenderingIntent|SpaceModel|PanelMode)|mp(oundPredicateType|arisonPredicateModifier))|ellStateValue|al(culationError|endarUnit))|T(ypesetterControlCharacterAction|imeZoneNameStyle|e(stComparisonOperation|xt(Block(Dimension|V(erticalAlignment|alueType)|Layer)|TableLayoutAlgorithm|FieldBezelStyle))|ableView(SelectionHighlightStyle|ColumnAutoresizingStyle)|rackingAreaOptions)|I(n(sertionPosition|te(rfaceStyle|ger))|mage(RepLoadStatus|Scaling|CacheMode|FrameStyle|LoadStatus|Alignment))|Ope(nGLPixelFormatAttribute|rationQueuePriority)|Date(Picker(Mode|Style)|Formatter(Behavior|Style))|U(RL(RequestCachePolicy|HandleStatus|C(acheStoragePolicy|redentialPersistence))|Integer)|P(o(stingStyle|int(ingDeviceType|erFunctionsOptions)|pUpArrowPosition)|athStyle|r(int(ing(Orientation|PaginationMode)|erTableStatus|PanelOptions)|opertyList(MutabilityOptions|Format)|edicateOperatorType))|ExpressionType|KeyValue(SetMutationKind|Change)|QTMovieLoopMode|F(indPanel(SubstringMatchType|Action)|o(nt(RenderingMode|FamilyClass)|cusRingPlacement))|W(hoseSubelementIdentifier|ind(ingRule|ow(B(utton|ackingLocation)|SharingType|CollectionBehavior)))|L(ine(MovementDirection|SweepDirection|CapStyle|JoinStyle)|evelIndicatorStyle)|Animation(BlockingMode|Curve))\\b", - "name": "support.type.cocoa.leopard" + "name": "support.type.cocoa.leopard.objc" }, { "match": "\\bC(I(Sampler|Co(ntext|lor)|Image(Accumulator)?|PlugIn(Registration)?|Vector|Kernel|Filter(Generator|Shape)?)|A(Renderer|MediaTiming(Function)?|BasicAnimation|ScrollLayer|Constraint(LayoutManager)?|T(iledLayer|extLayer|rans(ition|action))|OpenGLLayer|PropertyAnimation|KeyframeAnimation|Layer|A(nimation(Group)?|ction)))\\b", - "name": "support.class.quartz" + "name": "support.class.quartz.objc" }, { "match": "\\bC(G(Float|Point|Size|Rect)|IFormat|AConstraintAttribute)\\b", - "name": "support.type.quartz" + "name": "support.type.quartz.objc" }, { "match": "\\bNS(R(ect(Edge)?|ange)|G(lyph(Relation|LayoutMode)?|radientType)|M(odalSession|a(trixMode|p(Table|Enumerator)))|B(itmapImageFileType|orderType|uttonType|ezelStyle|ackingStoreType|rowserColumnResizingType)|S(cr(oll(er(Part|Arrow)|ArrowPosition)|eenAuxiliaryOpaque)|tringEncoding|ize|ocketNativeHandle|election(Granularity|Direction|Affinity)|wapped(Double|Float)|aveOperationType)|Ha(sh(Table|Enumerator)|ndler(2)?)|C(o(ntrol(Size|Tint)|mp(ositingOperation|arisonResult))|ell(State|Type|ImagePosition|Attribute))|T(hreadPrivate|ypesetterGlyphInfo|i(ckMarkPosition|tlePosition|meInterval)|o(ol(TipTag|bar(SizeMode|DisplayMode))|kenStyle)|IFFCompression|ext(TabType|Alignment)|ab(State|leViewDropOperation|ViewType)|rackingRectTag)|ImageInterpolation|Zone|OpenGL(ContextAuxiliary|PixelFormatAuxiliary)|D(ocumentChangeType|atePickerElementFlags|ra(werState|gOperation))|UsableScrollerParts|P(oint|r(intingPageOrder|ogressIndicator(Style|Th(ickness|readInfo))))|EventType|KeyValueObservingOptions|Fo(nt(SymbolicTraits|TraitMask|Action)|cusRingType)|W(indow(OrderingMode|Depth)|orkspace(IconCreationOptions|LaunchOptions)|ritingDirection)|L(ineBreakMode|ayout(Status|Direction))|A(nimation(Progress|Effect)|ppl(ication(TerminateReply|DelegateReply|PrintReply)|eEventManagerSuspensionID)|ffineTransformStruct|lertStyle))\\b", - "name": "support.type.cocoa" + "name": "support.type.cocoa.objc" }, { "match": "\\bNS(NotFound|Ordered(Ascending|Descending|Same))\\b", - "name": "support.constant.cocoa" + "name": "support.constant.cocoa.objc" }, { "match": "\\bNS(MenuDidBeginTracking|ViewDidUpdateTrackingAreas)?Notification\\b", - "name": "support.constant.notification.cocoa.leopard" + "name": "support.constant.notification.cocoa.leopard.objc" }, { "match": "\\bNS(Menu(Did(RemoveItem|SendAction|ChangeItem|EndTracking|AddItem)|WillSendAction)|S(ystemColorsDidChange|plitView(DidResizeSubviews|WillResizeSubviews))|C(o(nt(extHelpModeDid(Deactivate|Activate)|rolT(intDidChange|extDid(BeginEditing|Change|EndEditing)))|lor(PanelColorDidChange|ListDidChange)|mboBox(Selection(IsChanging|DidChange)|Will(Dismiss|PopUp)))|lassDescriptionNeededForClass)|T(oolbar(DidRemoveItem|WillAddItem)|ext(Storage(DidProcessEditing|WillProcessEditing)|Did(BeginEditing|Change|EndEditing)|View(DidChange(Selection|TypingAttributes)|WillChangeNotifyingTextView))|ableView(Selection(IsChanging|DidChange)|ColumnDid(Resize|Move)))|ImageRepRegistryDidChange|OutlineView(Selection(IsChanging|DidChange)|ColumnDid(Resize|Move)|Item(Did(Collapse|Expand)|Will(Collapse|Expand)))|Drawer(Did(Close|Open)|Will(Close|Open))|PopUpButton(CellWillPopUp|WillPopUp)|View(GlobalFrameDidChange|BoundsDidChange|F(ocusDidChange|rameDidChange))|FontSetChanged|W(indow(Did(Resi(ze|gn(Main|Key))|M(iniaturize|ove)|Become(Main|Key)|ChangeScreen(|Profile)|Deminiaturize|Update|E(ndSheet|xpose))|Will(M(iniaturize|ove)|BeginSheet|Close))|orkspace(SessionDid(ResignActive|BecomeActive)|Did(Mount|TerminateApplication|Unmount|PerformFileOperation|Wake|LaunchApplication)|Will(Sleep|Unmount|PowerOff|LaunchApplication)))|A(ntialiasThresholdChanged|ppl(ication(Did(ResignActive|BecomeActive|Hide|ChangeScreenParameters|U(nhide|pdate)|FinishLaunching)|Will(ResignActive|BecomeActive|Hide|Terminate|U(nhide|pdate)|FinishLaunching))|eEventManagerWillProcessFirstEvent)))Notification\\b", - "name": "support.constant.notification.cocoa" + "name": "support.constant.notification.cocoa.objc" }, { "match": "\\bNS(RuleEditor(RowType(Simple|Compound)|NestingMode(Si(ngle|mple)|Compound|List))|GradientDraws(BeforeStartingLocation|AfterEndingLocation)|M(inusSetExpressionType|a(chPortDeallocate(ReceiveRight|SendRight|None)|pTable(StrongMemory|CopyIn|ZeroingWeakMemory|ObjectPointerPersonality)))|B(oxCustom|undleExecutableArchitecture(X86|I386|PPC(64)?)|etweenPredicateOperatorType|ackgroundStyle(Raised|Dark|L(ight|owered)))|S(tring(DrawingTruncatesLastVisibleLine|EncodingConversion(ExternalRepresentation|AllowLossy))|ubqueryExpressionType|p(e(ech(SentenceBoundary|ImmediateBoundary|WordBoundary)|llingState(GrammarFlag|SpellingFlag))|litViewDividerStyleThi(n|ck))|e(rvice(RequestTimedOutError|M(iscellaneousError|alformedServiceDictionaryError)|InvalidPasteboardDataError|ErrorM(inimum|aximum)|Application(NotFoundError|LaunchFailedError))|gmentStyle(Round(Rect|ed)|SmallSquare|Capsule|Textured(Rounded|Square)|Automatic)))|H(UDWindowMask|ashTable(StrongMemory|CopyIn|ZeroingWeakMemory|ObjectPointerPersonality))|N(oModeColorPanel|etServiceNoAutoRename)|C(hangeRedone|o(ntainsPredicateOperatorType|l(orRenderingIntent(RelativeColorimetric|Saturation|Default|Perceptual|AbsoluteColorimetric)|lectorDisabledOption))|ellHit(None|ContentArea|TrackableArea|EditableTextArea))|T(imeZoneNameStyle(S(hort(Standard|DaylightSaving)|tandard)|DaylightSaving)|extFieldDatePickerStyle|ableViewSelectionHighlightStyle(Regular|SourceList)|racking(Mouse(Moved|EnteredAndExited)|CursorUpdate|InVisibleRect|EnabledDuringMouseDrag|A(ssumeInside|ctive(In(KeyWindow|ActiveApp)|WhenFirstResponder|Always))))|I(n(tersectSetExpressionType|dexedColorSpaceModel)|mageScale(None|Proportionally(Down|UpOrDown)|AxesIndependently))|Ope(nGLPFAAllowOfflineRenderers|rationQueue(DefaultMaxConcurrentOperationCount|Priority(High|Normal|Very(High|Low)|Low)))|D(iacriticInsensitiveSearch|ownloadsDirectory)|U(nionSetExpressionType|TF(16(BigEndianStringEncoding|StringEncoding|LittleEndianStringEncoding)|32(BigEndianStringEncoding|StringEncoding|LittleEndianStringEncoding)))|P(ointerFunctions(Ma(chVirtualMemory|llocMemory)|Str(ongMemory|uctPersonality)|C(StringPersonality|opyIn)|IntegerPersonality|ZeroingWeakMemory|O(paque(Memory|Personality)|bjectP(ointerPersonality|ersonality)))|at(hStyle(Standard|NavigationBar|PopUp)|ternColorSpaceModel)|rintPanelShows(Scaling|Copies|Orientation|P(a(perSize|ge(Range|SetupAccessory))|review)))|Executable(RuntimeMismatchError|NotLoadableError|ErrorM(inimum|aximum)|L(inkError|oadError)|ArchitectureMismatchError)|KeyValueObservingOption(Initial|Prior)|F(i(ndPanelSubstringMatchType(StartsWith|Contains|EndsWith|FullWord)|leRead(TooLargeError|UnknownStringEncodingError))|orcedOrderingSearch)|Wi(ndow(BackingLocation(MainMemory|Default|VideoMemory)|Sharing(Read(Only|Write)|None)|CollectionBehavior(MoveToActiveSpace|CanJoinAllSpaces|Default))|dthInsensitiveSearch)|AggregateExpressionType)\\b", - "name": "support.constant.cocoa.leopard" + "name": "support.constant.cocoa.leopard.objc" }, { "match": "\\bNS(R(GB(ModeColorPanel|ColorSpaceModel)|ight(Mouse(D(own(Mask)?|ragged(Mask)?)|Up(Mask)?)|T(ext(Movement|Alignment)|ab(sBezelBorder|StopType))|ArrowFunctionKey)|ound(RectBezelStyle|Bankers|ed(BezelStyle|TokenStyle|DisclosureBezelStyle)|Down|Up|Plain|Line(CapStyle|JoinStyle))|un(StoppedResponse|ContinuesResponse|AbortedResponse)|e(s(izableWindowMask|et(CursorRectsRunLoopOrdering|FunctionKey))|ce(ssedBezelStyle|iver(sCantHandleCommandScriptError|EvaluationScriptError))|turnTextMovement|doFunctionKey|quiredArgumentsMissingScriptError|l(evancyLevelIndicatorStyle|ative(Before|After))|gular(SquareBezelStyle|ControlSize)|moveTraitFontAction)|a(n(domSubelement|geDateMode)|tingLevelIndicatorStyle|dio(ModeMatrix|Button)))|G(IFFileType|lyph(Below|Inscribe(B(elow|ase)|Over(strike|Below)|Above)|Layout(WithPrevious|A(tAPoint|gainstAPoint))|A(ttribute(BidiLevel|Soft|Inscribe|Elastic)|bove))|r(ooveBorder|eaterThan(Comparison|OrEqualTo(Comparison|PredicateOperatorType)|PredicateOperatorType)|a(y(ModeColorPanel|ColorSpaceModel)|dient(None|Con(cave(Strong|Weak)|vex(Strong|Weak)))|phiteControlTint)))|XML(N(o(tationDeclarationKind|de(CompactEmptyElement|IsCDATA|OptionsNone|Use(SingleQuotes|DoubleQuotes)|Pre(serve(NamespaceOrder|C(haracterReferences|DATA)|DTD|Prefixes|E(ntities|mptyElements)|Quotes|Whitespace|A(ttributeOrder|ll))|ttyPrint)|ExpandEmptyElement))|amespaceKind)|CommentKind|TextKind|InvalidKind|D(ocument(X(MLKind|HTMLKind|Include)|HTMLKind|T(idy(XML|HTML)|extKind)|IncludeContentTypeDeclaration|Validate|Kind)|TDKind)|P(arser(GTRequiredError|XMLDeclNot(StartedError|FinishedError)|Mi(splaced(XMLDeclarationError|CDATAEndStringError)|xedContentDeclNot(StartedError|FinishedError))|S(t(andaloneValueError|ringNot(StartedError|ClosedError))|paceRequiredError|eparatorRequiredError)|N(MTOKENRequiredError|o(t(ationNot(StartedError|FinishedError)|WellBalancedError)|DTDError)|amespaceDeclarationError|AMERequiredError)|C(haracterRef(In(DTDError|PrologError|EpilogError)|AtEOFError)|o(nditionalSectionNot(StartedError|FinishedError)|mment(NotFinishedError|ContainsDoubleHyphenError))|DATANotFinishedError)|TagNameMismatchError|In(ternalError|valid(HexCharacterRefError|C(haracter(RefError|InEntityError|Error)|onditionalSectionError)|DecimalCharacterRefError|URIError|Encoding(NameError|Error)))|OutOfMemoryError|D(ocumentStartError|elegateAbortedParseError|OCTYPEDeclNotFinishedError)|U(RI(RequiredError|FragmentError)|n(declaredEntityError|parsedEntityError|knownEncodingError|finishedTagError))|P(CDATARequiredError|ublicIdentifierRequiredError|arsedEntityRef(MissingSemiError|NoNameError|In(Internal(SubsetError|Error)|PrologError|EpilogError)|AtEOFError)|r(ocessingInstructionNot(StartedError|FinishedError)|ematureDocumentEndError))|E(n(codingNotSupportedError|tity(Ref(In(DTDError|PrologError|EpilogError)|erence(MissingSemiError|WithoutNameError)|LoopError|AtEOFError)|BoundaryError|Not(StartedError|FinishedError)|Is(ParameterError|ExternalError)|ValueRequiredError))|qualExpectedError|lementContentDeclNot(StartedError|FinishedError)|xt(ernalS(tandaloneEntityError|ubsetNotFinishedError)|raContentError)|mptyDocumentError)|L(iteralNot(StartedError|FinishedError)|T(RequiredError|SlashRequiredError)|essThanSymbolInAttributeError)|Attribute(RedefinedError|HasNoValueError|Not(StartedError|FinishedError)|ListNot(StartedError|FinishedError)))|rocessingInstructionKind)|E(ntity(GeneralKind|DeclarationKind|UnparsedKind|P(ar(sedKind|ameterKind)|redefined))|lement(Declaration(MixedKind|UndefinedKind|E(lementKind|mptyKind)|Kind|AnyKind)|Kind))|Attribute(N(MToken(sKind|Kind)|otationKind)|CDATAKind|ID(Ref(sKind|Kind)|Kind)|DeclarationKind|En(tit(yKind|iesKind)|umerationKind)|Kind))|M(i(n(XEdge|iaturizableWindowMask|YEdge|uteCalendarUnit)|terLineJoinStyle|ddleSubelement|xedState)|o(nthCalendarUnit|deSwitchFunctionKey|use(Moved(Mask)?|E(ntered(Mask)?|ventSubtype|xited(Mask)?))|veToBezierPathElement|mentary(ChangeButton|Push(Button|InButton)|Light(Button)?))|enuFunctionKey|a(c(intoshInterfaceStyle|OSRomanStringEncoding)|tchesPredicateOperatorType|ppedRead|x(XEdge|YEdge))|ACHOperatingSystem)|B(MPFileType|o(ttomTabsBezelBorder|ldFontMask|rderlessWindowMask|x(Se(condary|parator)|OldStyle|Primary))|uttLineCapStyle|e(zelBorder|velLineJoinStyle|low(Bottom|Top)|gin(sWith(Comparison|PredicateOperatorType)|FunctionKey))|lueControlTint|ack(spaceCharacter|tabTextMovement|ingStore(Retained|Buffered|Nonretained)|TabCharacter|wardsSearch|groundTab)|r(owser(NoColumnResizing|UserColumnResizing|AutoColumnResizing)|eakFunctionKey))|S(h(ift(JISStringEncoding|KeyMask)|ow(ControlGlyphs|InvisibleGlyphs)|adowlessSquareBezelStyle)|y(s(ReqFunctionKey|tem(D(omainMask|efined(Mask)?)|FunctionKey))|mbolStringEncoding)|c(a(nnedOption|le(None|ToFit|Proportionally))|r(oll(er(NoPart|Increment(Page|Line|Arrow)|Decrement(Page|Line|Arrow)|Knob(Slot)?|Arrows(M(inEnd|axEnd)|None|DefaultSetting))|Wheel(Mask)?|LockFunctionKey)|eenChangedEventType))|t(opFunctionKey|r(ingDrawing(OneShot|DisableScreenFontSubstitution|Uses(DeviceMetrics|FontLeading|LineFragmentOrigin))|eam(Status(Reading|NotOpen|Closed|Open(ing)?|Error|Writing|AtEnd)|Event(Has(BytesAvailable|SpaceAvailable)|None|OpenCompleted|E(ndEncountered|rrorOccurred)))))|i(ngle(DateMode|UnderlineStyle)|ze(DownFontAction|UpFontAction))|olarisOperatingSystem|unOSOperatingSystem|pecialPageOrder|e(condCalendarUnit|lect(By(Character|Paragraph|Word)|i(ng(Next|Previous)|onAffinity(Downstream|Upstream))|edTab|FunctionKey)|gmentSwitchTracking(Momentary|Select(One|Any)))|quareLineCapStyle|witchButton|ave(ToOperation|Op(tions(Yes|No|Ask)|eration)|AsOperation)|mall(SquareBezelStyle|C(ontrolSize|apsFontMask)|IconButtonBezelStyle))|H(ighlightModeMatrix|SBModeColorPanel|o(ur(Minute(SecondDatePickerElementFlag|DatePickerElementFlag)|CalendarUnit)|rizontalRuler|meFunctionKey)|TTPCookieAcceptPolicy(Never|OnlyFromMainDocumentDomain|Always)|e(lp(ButtonBezelStyle|KeyMask|FunctionKey)|avierFontAction)|PUXOperatingSystem)|Year(MonthDa(yDatePickerElementFlag|tePickerElementFlag)|CalendarUnit)|N(o(n(StandardCharacterSetFontMask|ZeroWindingRule|activatingPanelMask|LossyASCIIStringEncoding)|Border|t(ification(SuspensionBehavior(Hold|Coalesce|D(eliverImmediately|rop))|NoCoalescing|CoalescingOn(Sender|Name)|DeliverImmediately|PostToAllSessions)|PredicateType|EqualToPredicateOperatorType)|S(cr(iptError|ollerParts)|ubelement|pecifierError)|CellMask|T(itle|opLevelContainersSpecifierError|abs(BezelBorder|NoBorder|LineBorder))|I(nterfaceStyle|mage)|UnderlineStyle|FontChangeAction)|u(ll(Glyph|CellType)|m(eric(Search|PadKeyMask)|berFormatter(Round(Half(Down|Up|Even)|Ceiling|Down|Up|Floor)|Behavior(10|Default)|S(cientificStyle|pellOutStyle)|NoStyle|CurrencyStyle|DecimalStyle|P(ercentStyle|ad(Before(Suffix|Prefix)|After(Suffix|Prefix))))))|e(t(Services(BadArgumentError|NotFoundError|C(ollisionError|ancelledError)|TimeoutError|InvalidError|UnknownError|ActivityInProgress)|workDomainMask)|wlineCharacter|xt(StepInterfaceStyle|FunctionKey))|EXTSTEPStringEncoding|a(t(iveShortGlyphPacking|uralTextAlignment)|rrowFontMask))|C(hange(ReadOtherContents|GrayCell(Mask)?|BackgroundCell(Mask)?|Cleared|Done|Undone|Autosaved)|MYK(ModeColorPanel|ColorSpaceModel)|ircular(BezelStyle|Slider)|o(n(stantValueExpressionType|t(inuousCapacityLevelIndicatorStyle|entsCellMask|ain(sComparison|erSpecifierError)|rol(Glyph|KeyMask))|densedFontMask)|lor(Panel(RGBModeMask|GrayModeMask|HSBModeMask|C(MYKModeMask|olorListModeMask|ustomPaletteModeMask|rayonModeMask)|WheelModeMask|AllModesMask)|ListModeColorPanel)|reServiceDirectory|m(p(osite(XOR|Source(In|O(ut|ver)|Atop)|Highlight|C(opy|lear)|Destination(In|O(ut|ver)|Atop)|Plus(Darker|Lighter))|ressedFontMask)|mandKeyMask))|u(stom(SelectorPredicateOperatorType|PaletteModeColorPanel)|r(sor(Update(Mask)?|PointingDevice)|veToBezierPathElement))|e(nterT(extAlignment|abStopType)|ll(State|H(ighlighted|as(Image(Horizontal|OnLeftOrBottom)|OverlappingImage))|ChangesContents|Is(Bordered|InsetButton)|Disabled|Editable|LightsBy(Gray|Background|Contents)|AllowsMixedState))|l(ipPagination|o(s(ePathBezierPathElement|ableWindowMask)|ckAndCalendarDatePickerStyle)|ear(ControlTint|DisplayFunctionKey|LineFunctionKey))|a(seInsensitive(Search|PredicateOption)|n(notCreateScriptCommandError|cel(Button|TextMovement))|chesDirectory|lculation(NoError|Overflow|DivideByZero|Underflow|LossOfPrecision)|rriageReturnCharacter)|r(itical(Request|AlertStyle)|ayonModeColorPanel))|T(hick(SquareBezelStyle|erSquareBezelStyle)|ypesetter(Behavior|HorizontalTabAction|ContainerBreakAction|ZeroAdvancementAction|OriginalBehavior|ParagraphBreakAction|WhitespaceAction|L(ineBreakAction|atestBehavior))|i(ckMark(Right|Below|Left|Above)|tledWindowMask|meZoneDatePickerElementFlag)|o(olbarItemVisibilityPriority(Standard|High|User|Low)|pTabsBezelBorder|ggleButton)|IFF(Compression(N(one|EXT)|CCITTFAX(3|4)|OldJPEG|JPEG|PackBits|LZW)|FileType)|e(rminate(Now|Cancel|Later)|xt(Read(InapplicableDocumentTypeError|WriteErrorM(inimum|aximum))|Block(M(i(nimum(Height|Width)|ddleAlignment)|a(rgin|ximum(Height|Width)))|B(o(ttomAlignment|rder)|aselineAlignment)|Height|TopAlignment|P(ercentageValueType|adding)|Width|AbsoluteValueType)|StorageEdited(Characters|Attributes)|CellType|ured(RoundedBezelStyle|BackgroundWindowMask|SquareBezelStyle)|Table(FixedLayoutAlgorithm|AutomaticLayoutAlgorithm)|Field(RoundedBezel|SquareBezel|AndStepperDatePickerStyle)|WriteInapplicableDocumentTypeError|ListPrependEnclosingMarker))|woByteGlyphPacking|ab(Character|TextMovement|le(tP(oint(Mask|EventSubtype)?|roximity(Mask|EventSubtype)?)|Column(NoResizing|UserResizingMask|AutoresizingMask)|View(ReverseSequentialColumnAutoresizingStyle|GridNone|S(olid(HorizontalGridLineMask|VerticalGridLineMask)|equentialColumnAutoresizingStyle)|NoColumnAutoresizing|UniformColumnAutoresizingStyle|FirstColumnOnlyAutoresizingStyle|LastColumnOnlyAutoresizingStyle)))|rackModeMatrix)|I(n(sert(CharFunctionKey|FunctionKey|LineFunctionKey)|t(Type|ernalS(criptError|pecifierError))|dexSubelement|validIndexSpecifierError|formational(Request|AlertStyle)|PredicateOperatorType)|talicFontMask|SO(2022JPStringEncoding|Latin(1StringEncoding|2StringEncoding))|dentityMappingCharacterCollection|llegalTextMovement|mage(R(ight|ep(MatchesDevice|LoadStatus(ReadingHeader|Completed|InvalidData|Un(expectedEOF|knownType)|WillNeedAllData)))|Below|C(ellType|ache(BySize|Never|Default|Always))|Interpolation(High|None|Default|Low)|O(nly|verlaps)|Frame(Gr(oove|ayBezel)|Button|None|Photo)|L(oadStatus(ReadError|C(ompleted|ancelled)|InvalidData|UnexpectedEOF)|eft)|A(lign(Right|Bottom(Right|Left)?|Center|Top(Right|Left)?|Left)|bove)))|O(n(State|eByteGlyphPacking|OffButton|lyScrollerArrows)|ther(Mouse(D(own(Mask)?|ragged(Mask)?)|Up(Mask)?)|TextMovement)|SF1OperatingSystem|pe(n(GL(GO(Re(setLibrary|tainRenderers)|ClearFormatCache|FormatCacheSize)|PFA(R(obust|endererID)|M(inimumPolicy|ulti(sample|Screen)|PSafe|aximumPolicy)|BackingStore|S(creenMask|te(ncilSize|reo)|ingleRenderer|upersample|ample(s|Buffers|Alpha))|NoRecovery|C(o(lor(Size|Float)|mpliant)|losestPolicy)|OffScreen|D(oubleBuffer|epthSize)|PixelBuffer|VirtualScreenCount|FullScreen|Window|A(cc(umSize|elerated)|ux(Buffers|DepthStencil)|l(phaSize|lRenderers))))|StepUnicodeReservedBase)|rationNotSupportedForKeyS(criptError|pecifierError))|ffState|KButton|rPredicateType|bjC(B(itfield|oolType)|S(hortType|tr(ingType|uctType)|electorType)|NoType|CharType|ObjectType|DoubleType|UnionType|PointerType|VoidType|FloatType|Long(Type|longType)|ArrayType))|D(i(s(c(losureBezelStyle|reteCapacityLevelIndicatorStyle)|playWindowRunLoopOrdering)|acriticInsensitivePredicateOption|rect(Selection|PredicateModifier))|o(c(ModalWindowMask|ument(Directory|ationDirectory))|ubleType|wn(TextMovement|ArrowFunctionKey))|e(s(cendingPageOrder|ktopDirectory)|cimalTabStopType|v(ice(NColorSpaceModel|IndependentModifierFlagsMask)|eloper(Directory|ApplicationDirectory))|fault(ControlTint|TokenStyle)|lete(Char(acter|FunctionKey)|FunctionKey|LineFunctionKey)|moApplicationDirectory)|a(yCalendarUnit|teFormatter(MediumStyle|Behavior(10|Default)|ShortStyle|NoStyle|FullStyle|LongStyle))|ra(wer(Clos(ingState|edState)|Open(ingState|State))|gOperation(Generic|Move|None|Copy|Delete|Private|Every|Link|All)))|U(ser(CancelledError|D(irectory|omainMask)|FunctionKey)|RL(Handle(NotLoaded|Load(Succeeded|InProgress|Failed))|CredentialPersistence(None|Permanent|ForSession))|n(scaledWindowMask|cachedRead|i(codeStringEncoding|talicFontMask|fiedTitleAndToolbarWindowMask)|d(o(CloseGroupingRunLoopOrdering|FunctionKey)|e(finedDateComponent|rline(Style(Single|None|Thick|Double)|Pattern(Solid|D(ot|ash(Dot(Dot)?)?)))))|known(ColorSpaceModel|P(ointingDevice|ageOrder)|KeyS(criptError|pecifierError))|boldFontMask)|tilityWindowMask|TF8StringEncoding|p(dateWindowsRunLoopOrdering|TextMovement|ArrowFunctionKey))|J(ustifiedTextAlignment|PEG(2000FileType|FileType)|apaneseEUC(GlyphPacking|StringEncoding))|P(o(s(t(Now|erFontMask|WhenIdle|ASAP)|iti(on(Replace|Be(fore|ginning)|End|After)|ve(IntType|DoubleType|FloatType)))|pUp(NoArrow|ArrowAt(Bottom|Center))|werOffEventType|rtraitOrientation)|NGFileType|ush(InCell(Mask)?|OnPushOffButton)|e(n(TipMask|UpperSideMask|PointingDevice|LowerSideMask)|riodic(Mask)?)|P(S(caleField|tatus(Title|Field)|aveButton)|N(ote(Title|Field)|ame(Title|Field))|CopiesField|TitleField|ImageButton|OptionsButton|P(a(perFeedButton|ge(Range(To|From)|ChoiceMatrix))|reviewButton)|LayoutButton)|lainTextTokenStyle|a(useFunctionKey|ragraphSeparatorCharacter|ge(DownFunctionKey|UpFunctionKey))|r(int(ing(ReplyLater|Success|Cancelled|Failure)|ScreenFunctionKey|erTable(NotFound|OK|Error)|FunctionKey)|o(p(ertyList(XMLFormat|MutableContainers(AndLeaves)?|BinaryFormat|Immutable|OpenStepFormat)|rietaryStringEncoding)|gressIndicator(BarStyle|SpinningStyle|Preferred(SmallThickness|Thickness|LargeThickness|AquaThickness)))|e(ssedTab|vFunctionKey))|L(HeightForm|CancelButton|TitleField|ImageButton|O(KButton|rientationMatrix)|UnitsButton|PaperNameButton|WidthForm))|E(n(terCharacter|d(sWith(Comparison|PredicateOperatorType)|FunctionKey))|v(e(nOddWindingRule|rySubelement)|aluatedObjectExpressionType)|qualTo(Comparison|PredicateOperatorType)|ra(serPointingDevice|CalendarUnit|DatePickerElementFlag)|x(clude(10|QuickDrawElementsIconCreationOption)|pandedFontMask|ecuteFunctionKey))|V(i(ew(M(in(XMargin|YMargin)|ax(XMargin|YMargin))|HeightSizable|NotSizable|WidthSizable)|aPanelFontAction)|erticalRuler|a(lidationErrorM(inimum|aximum)|riableExpressionType))|Key(SpecifierEvaluationScriptError|Down(Mask)?|Up(Mask)?|PathExpressionType|Value(MinusSetMutation|SetSetMutation|Change(Re(placement|moval)|Setting|Insertion)|IntersectSetMutation|ObservingOption(New|Old)|UnionSetMutation|ValidationError))|QTMovie(NormalPlayback|Looping(BackAndForthPlayback|Playback))|F(1(1FunctionKey|7FunctionKey|2FunctionKey|8FunctionKey|3FunctionKey|9FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey|6FunctionKey)|7FunctionKey|i(nd(PanelAction(Replace(A(ndFind|ll(InSelection)?))?|S(howFindPanel|e(tFindString|lectAll(InSelection)?))|Next|Previous)|FunctionKey)|tPagination|le(Read(No(SuchFileError|PermissionError)|CorruptFileError|In(validFileNameError|applicableStringEncodingError)|Un(supportedSchemeError|knownError))|HandlingPanel(CancelButton|OKButton)|NoSuchFileError|ErrorM(inimum|aximum)|Write(NoPermissionError|In(validFileNameError|applicableStringEncodingError)|OutOfSpaceError|Un(supportedSchemeError|knownError))|LockingError)|xedPitchFontMask)|2(1FunctionKey|7FunctionKey|2FunctionKey|8FunctionKey|3FunctionKey|9FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey|6FunctionKey)|o(nt(Mo(noSpaceTrait|dernSerifsClass)|BoldTrait|S(ymbolicClass|criptsClass|labSerifsClass|ansSerifClass)|C(o(ndensedTrait|llectionApplicationOnlyMask)|larendonSerifsClass)|TransitionalSerifsClass|I(ntegerAdvancementsRenderingMode|talicTrait)|O(ldStyleSerifsClass|rnamentalsClass)|DefaultRenderingMode|U(nknownClass|IOptimizedTrait)|Panel(S(hadowEffectModeMask|t(andardModesMask|rikethroughEffectModeMask)|izeModeMask)|CollectionModeMask|TextColorEffectModeMask|DocumentColorEffectModeMask|UnderlineEffectModeMask|FaceModeMask|All(ModesMask|EffectsModeMask))|ExpandedTrait|VerticalTrait|F(amilyClassMask|reeformSerifsClass)|Antialiased(RenderingMode|IntegerAdvancementsRenderingMode))|cusRing(Below|Type(None|Default|Exterior)|Only|Above)|urByteGlyphPacking|rm(attingError(M(inimum|aximum))?|FeedCharacter))|8FunctionKey|unction(ExpressionType|KeyMask)|3(1FunctionKey|2FunctionKey|3FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey)|9FunctionKey|4FunctionKey|P(RevertButton|S(ize(Title|Field)|etButton)|CurrentField|Preview(Button|Field))|l(oat(ingPointSamplesBitmapFormat|Type)|agsChanged(Mask)?)|axButton|5FunctionKey|6FunctionKey)|W(heelModeColorPanel|indow(s(NTOperatingSystem|CP125(1StringEncoding|2StringEncoding|3StringEncoding|4StringEncoding|0StringEncoding)|95(InterfaceStyle|OperatingSystem))|M(iniaturizeButton|ovedEventType)|Below|CloseButton|ToolbarButton|ZoomButton|Out|DocumentIconButton|ExposedEventType|Above)|orkspaceLaunch(NewInstance|InhibitingBackgroundOnly|Default|PreferringClassic|WithoutA(ctivation|ddingToRecents)|A(sync|nd(Hide(Others)?|Print)|llowingClassicStartup))|eek(day(CalendarUnit|OrdinalCalendarUnit)|CalendarUnit)|a(ntsBidiLevels|rningAlertStyle)|r(itingDirection(RightToLeft|Natural|LeftToRight)|apCalendarComponents))|L(i(stModeMatrix|ne(Moves(Right|Down|Up|Left)|B(order|reakBy(C(harWrapping|lipping)|Truncating(Middle|Head|Tail)|WordWrapping))|S(eparatorCharacter|weep(Right|Down|Up|Left))|ToBezierPathElement|DoesntMove|arSlider)|teralSearch|kePredicateOperatorType|ghterFontAction|braryDirectory)|ocalDomainMask|e(ssThan(Comparison|OrEqualTo(Comparison|PredicateOperatorType)|PredicateOperatorType)|ft(Mouse(D(own(Mask)?|ragged(Mask)?)|Up(Mask)?)|T(ext(Movement|Alignment)|ab(sBezelBorder|StopType))|ArrowFunctionKey))|a(yout(RightToLeft|NotDone|CantFit|OutOfGlyphs|Done|LeftToRight)|ndscapeOrientation)|ABColorSpaceModel)|A(sc(iiWithDoubleByteEUCGlyphPacking|endingPageOrder)|n(y(Type|PredicateModifier|EventMask)|choredSearch|imation(Blocking|Nonblocking(Threaded)?|E(ffect(DisappearingItemDefault|Poof)|ase(In(Out)?|Out))|Linear)|dPredicateType)|t(Bottom|tachmentCharacter|omicWrite|Top)|SCIIStringEncoding|d(obe(GB1CharacterCollection|CNS1CharacterCollection|Japan(1CharacterCollection|2CharacterCollection)|Korea1CharacterCollection)|dTraitFontAction|minApplicationDirectory)|uto(saveOperation|Pagination)|pp(lication(SupportDirectory|D(irectory|e(fined(Mask)?|legateReply(Success|Cancel|Failure)|activatedEventType))|ActivatedEventType)|KitDefined(Mask)?)|l(ternateKeyMask|pha(ShiftKeyMask|NonpremultipliedBitmapFormat|FirstBitmapFormat)|ert(SecondButtonReturn|ThirdButtonReturn|OtherReturn|DefaultReturn|ErrorReturn|FirstButtonReturn|AlternateReturn)|l(ScrollerParts|DomainsMask|PredicateModifier|LibrariesDirectory|ApplicationsDirectory))|rgument(sWrongScriptError|EvaluationScriptError)|bove(Bottom|Top)|WTEventType))\\b", - "name": "support.constant.cocoa" + "name": "support.constant.cocoa.objc" }, { - "include": "source.c" + "include": "#c_lang" }, { "include": "#bracketed_content" } ], "repository": { + "c_lang": { + "patterns": [ + { + "include": "#preprocessor-rule-enabled" + }, + { + "include": "#preprocessor-rule-disabled" + }, + { + "include": "#preprocessor-rule-conditional" + }, + { + "include": "#comments" + }, + { + "include": "#switch_statement" + }, + { + "match": "\\b(break|continue|do|else|for|goto|if|_Pragma|return|while)\\b", + "name": "keyword.control.objc" + }, + { + "include": "#storage_types" + }, + { + "match": "typedef", + "name": "keyword.other.typedef.objc" + }, + { + "match": "\\b(const|extern|register|restrict|static|volatile|inline)\\b", + "name": "storage.modifier.objc" + }, + { + "match": "\\bk[A-Z]\\w*\\b", + "name": "constant.other.variable.mac-classic.objc" + }, + { + "match": "\\bg[A-Z]\\w*\\b", + "name": "variable.other.readwrite.global.mac-classic.objc" + }, + { + "match": "\\bs[A-Z]\\w*\\b", + "name": "variable.other.readwrite.static.mac-classic.objc" + }, + { + "match": "\\b(NULL|true|false|TRUE|FALSE)\\b", + "name": "constant.language.objc" + }, + { + "include": "#operators" + }, + { + "include": "#numbers" + }, + { + "include": "#strings" + }, + { + "begin": "(?x)\n^\\s* ((\\#)\\s*define) \\s+\t# define\n((?[a-zA-Z_$][\\w$]*))\t # macro name\n(?:\n (\\()\n\t(\n\t \\s* \\g \\s*\t\t # first argument\n\t ((,) \\s* \\g \\s*)* # additional arguments\n\t (?:\\.\\.\\.)?\t\t\t# varargs ellipsis?\n\t)\n (\\))\n)?", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.define.objc" + }, + "2": { + "name": "punctuation.definition.directive.objc" + }, + "3": { + "name": "entity.name.function.preprocessor.objc" + }, + "5": { + "name": "punctuation.definition.parameters.begin.objc" + }, + "6": { + "name": "variable.parameter.preprocessor.objc" + }, + "8": { + "name": "punctuation.separator.parameters.objc" + }, + "9": { + "name": "punctuation.definition.parameters.end.objc" + } + }, + "end": "(?=(?://|/\\*))|(?", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objc" + } + }, + "name": "string.quoted.other.lt-gt.include.objc" + } + ] + }, + { + "include": "#pragma-mark" + }, + { + "begin": "^\\s*((#)\\s*line)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.line.objc" + }, + "2": { + "name": "punctuation.definition.directive.objc" + } + }, + "end": "(?=(?://|/\\*))|(?\\]\\)]))\\s*([a-zA-Z_]\\w*)\\s*(?=(?:\\[\\]\\s*)?(?:,|\\)))", + "captures": { + "1": { + "name": "variable.parameter.probably.objc" + } + } + }, + "access-method": { + "name": "meta.function-call.member.objc", + "begin": "([a-zA-Z_][a-zA-Z_0-9]*|(?<=[\\]\\)]))\\s*(?:(\\.)|(->))((?:(?:[a-zA-Z_][a-zA-Z_0-9]*)\\s*(?:(?:\\.)|(?:->)))*)\\s*([a-zA-Z_][a-zA-Z_0-9]*)(\\()", + "beginCaptures": { + "1": { + "name": "variable.object.objc" + }, + "2": { + "name": "punctuation.separator.dot-access.objc" + }, + "3": { + "name": "punctuation.separator.pointer-access.objc" + }, + "4": { + "patterns": [ + { + "match": "\\.", + "name": "punctuation.separator.dot-access.objc" + }, + { + "match": "->", + "name": "punctuation.separator.pointer-access.objc" + }, + { + "match": "[a-zA-Z_][a-zA-Z_0-9]*", + "name": "variable.object.objc" + }, + { + "name": "everything.else.objc", + "match": ".+" + } + ] + }, + "5": { + "name": "entity.name.function.member.objc" + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.function.member.objc" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.arguments.end.bracket.round.function.member.objc" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + "block": { + "patterns": [ + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objc" + } + }, + "end": "}|(?=\\s*#\\s*(?:elif|else|endif)\\b)", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.bracket.curly.objc" + } + }, + "name": "meta.block.objc", + "patterns": [ + { + "include": "#block_innards" + } + ] + } + ] + }, + "block_innards": { + "patterns": [ + { + "include": "#preprocessor-rule-enabled-block" + }, + { + "include": "#preprocessor-rule-disabled-block" + }, + { + "include": "#preprocessor-rule-conditional-block" + }, + { + "include": "#method_access" + }, + { + "include": "#member_access" + }, + { + "include": "#c_function_call" + }, + { + "name": "meta.initialization.objc", + "begin": "(?x)\n(?:\n (?:\n\t(?=\\s)(?=+!]+ | \\(\\) | \\[\\]))\n)\n\\s*(\\() # opening bracket", + "beginCaptures": { + "1": { + "name": "variable.other.objc" + }, + "2": { + "name": "punctuation.section.parens.begin.bracket.round.initialization.objc" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.initialization.objc" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.objc" + } + }, + "end": "}|(?=\\s*#\\s*(?:elif|else|endif)\\b)", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.bracket.curly.objc" + } + }, + "patterns": [ + { + "include": "#block_innards" + } + ] + }, + { + "include": "#parens-block" + }, + { + "include": "$base" + } + ] + }, + "c_function_call": { + "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate|and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas)\\s*\\()\n(?=\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++\\s*\\( # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", + "end": "(?<=\\))(?!\\w)", + "name": "meta.function-call.objc", + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + "comments": { + "patterns": [ + { + "captures": { + "1": { + "name": "meta.toc-list.banner.block.objc" + } + }, + "match": "^/\\* =(\\s*.*?)\\s*= \\*/$\\n?", + "name": "comment.block.objc" + }, + { + "begin": "/\\*", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.begin.objc" + } + }, + "end": "\\*/", + "endCaptures": { + "0": { + "name": "punctuation.definition.comment.end.objc" + } + }, + "name": "comment.block.objc" + }, + { + "captures": { + "1": { + "name": "meta.toc-list.banner.line.objc" + } + }, + "match": "^// =(\\s*.*?)\\s*=\\s*$\\n?", + "name": "comment.line.banner.objc" + }, + { + "begin": "(^[ \\t]+)?(?=//)", + "beginCaptures": { + "1": { + "name": "punctuation.whitespace.comment.leading.objc" + } + }, + "end": "(?!\\G)", + "patterns": [ + { + "begin": "//", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.objc" + } + }, + "end": "(?=\\n)", + "name": "comment.line.double-slash.objc", + "patterns": [ + { + "include": "#line_continuation_character" + } + ] + } + ] + } + ] + }, + "disabled": { + "begin": "^\\s*#\\s*if(n?def)?\\b.*$", + "end": "^\\s*#\\s*endif\\b", + "patterns": [ + { + "include": "#disabled" + }, + { + "include": "#pragma-mark" + } + ] + }, + "line_continuation_character": { + "patterns": [ + { + "match": "(\\\\)\\n", + "captures": { + "1": { + "name": "constant.character.escape.line-continuation.objc" + } + } + } + ] + }, + "parens": { + "name": "meta.parens.objc", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objc" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objc" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + "parens-block": { + "name": "meta.parens.block.objc", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objc" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objc" + } + }, + "patterns": [ + { + "include": "#block_innards" + }, + { + "match": "(?-mix:(?>=|\\|=", + "name": "keyword.operator.assignment.compound.bitwise.objc" + }, + { + "match": "<<|>>", + "name": "keyword.operator.bitwise.shift.objc" + }, + { + "match": "!=|<=|>=|==|<|>", + "name": "keyword.operator.comparison.objc" + }, + { + "match": "&&|!|\\|\\|", + "name": "keyword.operator.logical.objc" + }, + { + "match": "&|\\||\\^|~", + "name": "keyword.operator.objc" + }, + { + "match": "=", + "name": "keyword.operator.assignment.objc" + }, + { + "match": "%|\\*|/|-|\\+", + "name": "keyword.operator.objc" + }, + { + "begin": "(\\?)", + "beginCaptures": { + "1": { + "name": "keyword.operator.ternary.objc" + } + }, + "end": "(:)", + "endCaptures": { + "1": { + "name": "keyword.operator.ternary.objc" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + }, + { + "include": "$base" + } + ] + } + ] + }, + "strings": { + "patterns": [ + { + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.objc" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objc" + } + }, + "name": "string.quoted.double.objc", + "patterns": [ + { + "include": "#string_escaped_char" + }, + { + "include": "#string_placeholder" + }, + { + "include": "#line_continuation_character" + } + ] + }, + { + "begin": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.objc" + } + }, + "end": "'", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.objc" + } + }, + "name": "string.quoted.single.objc", + "patterns": [ + { + "include": "#string_escaped_char" + }, + { + "include": "#line_continuation_character" + } + ] + } + ] + }, + "string_escaped_char": { + "patterns": [ + { + "match": "(?x)\\\\ (\n\\\\\t\t\t |\n[abefnprtv'\"?] |\n[0-3]\\d{,2}\t |\n[4-7]\\d?\t\t|\nx[a-fA-F0-9]{,2} |\nu[a-fA-F0-9]{,4} |\nU[a-fA-F0-9]{,8} )", + "name": "constant.character.escape.objc" + }, + { + "match": "\\\\.", + "name": "invalid.illegal.unknown-escape.objc" + } + ] + }, + "string_placeholder": { + "patterns": [ + { + "match": "(?x) %\n(\\d+\\$)?\t\t\t\t\t\t # field (argument #)\n[#0\\- +']*\t\t\t\t\t\t # flags\n[,;:_]?\t\t\t\t\t\t\t # separator character (AltiVec)\n((-?\\d+)|\\*(-?\\d+\\$)?)?\t\t # minimum field width\n(\\.((-?\\d+)|\\*(-?\\d+\\$)?)?)?\t# precision\n(hh|h|ll|l|j|t|z|q|L|vh|vl|v|hv|hl)? # length modifier\n[diouxXDOUeEfFgGaACcSspn%]\t\t # conversion type", + "name": "constant.other.placeholder.objc" + }, + { + "match": "(%)(?!\"\\s*(PRI|SCN))", + "captures": { + "1": { + "name": "invalid.illegal.placeholder.objc" + } + } + } + ] + }, + "storage_types": { + "patterns": [ + { + "match": "(?-mix:(?=+!]+|\\(\\)|\\[\\]))\\s*\\(\n)", + "end": "(?<=\\))(?!\\w)|(?=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.objc" + }, + "2": { + "name": "punctuation.section.arguments.begin.bracket.round.objc" + } + }, + "end": "(\\))|(?=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.objc" + }, + "2": { + "name": "punctuation.section.parameters.begin.bracket.round.objc" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parameters.end.bracket.round.objc" + } + }, + "patterns": [ + { + "include": "#probably_a_parameter" + }, + { + "include": "#function-innards" + } + ] + }, + { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objc" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objc" + } + }, + "patterns": [ + { + "include": "#function-innards" + } + ] + }, + { + "include": "$base" + } + ] + }, + "function-call-innards": { + "patterns": [ + { + "include": "#comments" + }, + { + "include": "#storage_types" + }, + { + "include": "#method_access" + }, + { + "include": "#member_access" + }, + { + "include": "#operators" + }, + { + "begin": "(?x)\n(?!(?:while|for|do|if|else|switch|catch|enumerate|return|typeid|alignof|alignas|sizeof|[cr]?iterate|and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|alignof|alignas)\\s*\\()\n(\n(?:[A-Za-z_][A-Za-z0-9_]*+|::)++ # actual name\n|\n(?:(?<=operator)(?:[-*&<>=+!]+|\\(\\)|\\[\\]))\n)\n\\s*(\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.objc" + }, + "2": { + "name": "punctuation.section.arguments.begin.bracket.round.objc" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.arguments.end.bracket.round.objc" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.objc" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.objc" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + { + "include": "#block_innards" + } + ] + }, + "default_statement": { + "name": "meta.conditional.case.objc", + "begin": "((?\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.switch.objc", + "begin": "\\G ?", + "end": "((?:\\{|(?=;)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.begin.bracket.curly.switch.objc" + } + }, + "patterns": [ + { + "include": "#switch_conditional_parentheses" + }, + { + "include": "$base" + } + ] + }, + { + "name": "meta.body.switch.objc", + "begin": "(?<=\\{)", + "end": "(\\})", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.switch.objc" + } + }, + "patterns": [ + { + "include": "#default_statement" + }, + { + "include": "#case_statement" + }, + { + "include": "$base" + }, + { + "include": "#block_innards" + } + ] + }, + { + "name": "meta.tail.switch.objc", + "begin": "(?<=})[\\s\\n]*", + "end": "[\\s\\n]*(?=;)", + "patterns": [ + { + "include": "$base" + } + ] + } + ] + }, + "switch_conditional_parentheses": { + "name": "meta.conditional.switch.objc", + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.section.parens.begin.bracket.round.conditional.switch.objc" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.conditional.switch.objc" + } + }, + "patterns": [ + { + "include": "#conditional_context" + } + ] + }, + "static_assert": { + "begin": "(static_assert|_Static_assert)\\s*(\\()", + "beginCaptures": { + "1": { + "name": "keyword.other.static_assert.objc" + }, + "2": { + "name": "punctuation.section.arguments.begin.bracket.round.objc" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.objc" + } + }, + "patterns": [ + { + "name": "meta.static_assert.message.objc", + "begin": "(,)\\s*(?=(?:L|u8|u|U\\s*\\\")?)", + "beginCaptures": { + "1": { + "name": "punctuation.separator.delimiter.objc" + } + }, + "end": "(?=\\))", + "patterns": [ + { + "include": "#string_context" + }, + { + "include": "#string_context_c" + } + ] + }, + { + "include": "#function_call_context" + } + ] + }, + "conditional_context": { + "patterns": [ + { + "include": "$base" + }, + { + "include": "#block_innards" + } + ] + }, + "member_access": { + "match": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))((?:[a-zA-Z_]\\w*\\s*(?-mix:(?:(?:\\.\\*|\\.))|(?:(?:->\\*|->)))\\s*)*)\\s*(\\b(?!(?:void|char|short|int|signed|unsigned|long|float|double|bool|_Bool|_Complex|_Imaginary|u_char|u_short|u_int|u_long|ushort|uint|u_quad_t|quad_t|qaddr_t|caddr_t|daddr_t|div_t|dev_t|fixpt_t|blkcnt_t|blksize_t|gid_t|in_addr_t|in_port_t|ino_t|key_t|mode_t|nlink_t|id_t|pid_t|off_t|segsz_t|swblk_t|uid_t|id_t|clock_t|size_t|ssize_t|time_t|useconds_t|suseconds_t|pthread_attr_t|pthread_cond_t|pthread_condattr_t|pthread_mutex_t|pthread_mutexattr_t|pthread_once_t|pthread_rwlock_t|pthread_rwlockattr_t|pthread_t|pthread_key_t|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|int_least8_t|int_least16_t|int_least32_t|int_least64_t|uint_least8_t|uint_least16_t|uint_least32_t|uint_least64_t|int_fast8_t|int_fast16_t|int_fast32_t|int_fast64_t|uint_fast8_t|uint_fast16_t|uint_fast32_t|uint_fast64_t|intptr_t|uintptr_t|intmax_t|intmax_t|uintmax_t|uintmax_t|memory_order|atomic_bool|atomic_char|atomic_schar|atomic_uchar|atomic_short|atomic_ushort|atomic_int|atomic_uint|atomic_long|atomic_ulong|atomic_llong|atomic_ullong|atomic_char16_t|atomic_char32_t|atomic_wchar_t|atomic_int_least8_t|atomic_uint_least8_t|atomic_int_least16_t|atomic_uint_least16_t|atomic_int_least32_t|atomic_uint_least32_t|atomic_int_least64_t|atomic_uint_least64_t|atomic_int_fast8_t|atomic_uint_fast8_t|atomic_int_fast16_t|atomic_uint_fast16_t|atomic_int_fast32_t|atomic_uint_fast32_t|atomic_int_fast64_t|atomic_uint_fast64_t|atomic_intptr_t|atomic_uintptr_t|atomic_size_t|atomic_ptrdiff_t|atomic_intmax_t|atomic_uintmax_t))[a-zA-Z_]\\w*\\b(?!\\())", + "captures": { + "1": { + "name": "variable.other.object.access.objc" + }, + "2": { + "name": "punctuation.separator.dot-access.objc" + }, + "3": { + "name": "punctuation.separator.pointer-access.objc" + }, + "4": { + "patterns": [ + { + "include": "#member_access" + }, + { + "include": "#method_access" + }, + { + "match": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))", + "captures": { + "1": { + "name": "variable.other.object.access.objc" + }, + "2": { + "name": "punctuation.separator.dot-access.objc" + }, + "3": { + "name": "punctuation.separator.pointer-access.objc" + } + } + } + ] + }, + "5": { + "name": "variable.other.member.objc" + } + } + }, + "method_access": { + "contentName": "meta.function-call.member.objc", + "begin": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))((?:[a-zA-Z_]\\w*\\s*(?-mix:(?:(?:\\.\\*|\\.))|(?:(?:->\\*|->)))\\s*)*)\\s*([a-zA-Z_]\\w*)(\\()", + "beginCaptures": { + "1": { + "name": "variable.other.object.access.objc" + }, + "2": { + "name": "punctuation.separator.dot-access.objc" + }, + "3": { + "name": "punctuation.separator.pointer-access.objc" + }, + "4": { + "patterns": [ + { + "include": "#member_access" + }, + { + "include": "#method_access" + }, + { + "match": "((?:[a-zA-Z_]\\w*|(?<=\\]|\\)))\\s*)(?:((?:\\.\\*|\\.))|((?:->\\*|->)))", + "captures": { + "1": { + "name": "variable.other.object.access.objc" + }, + "2": { + "name": "punctuation.separator.dot-access.objc" + }, + "3": { + "name": "punctuation.separator.pointer-access.objc" + } + } + } + ] + }, + "5": { + "name": "entity.name.function.member.objc" + }, + "6": { + "name": "punctuation.section.arguments.begin.bracket.round.function.member.objc" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.arguments.end.bracket.round.function.member.objc" + } + }, + "patterns": [ + { + "include": "#function-call-innards" + } + ] + }, + "numbers": { + "begin": "(? + +/* + Multi + Line + Comments +*/ +@implementation Test + +- (void) applicationWillFinishLaunching:(NSNotification *)notification +{ +} + +- (IBAction)onSelectInput:(id)sender +{ + NSString* defaultDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true)[0]; + + NSOpenPanel* panel = [NSOpenPanel openPanel]; + [panel setAllowedFileTypes:[[NSArray alloc] initWithObjects:@"ipa", @"xcarchive", @"app", nil]]; + + [panel beginWithCompletionHandler:^(NSInteger result) + { + if (result == NSFileHandlingPanelOKButton) + [self.inputTextField setStringValue:[panel.URL path]]; + }]; + return YES; + + int hex = 0xFEF1F0F; + float ing = 3.14; + ing = 3.14e0; + ing = 31.4e-2; +} + +-(id) initWithParams:(id) aHandler withDeviceStateManager:(id) deviceStateManager +{ + // add a tap gesture recognizer + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; + NSMutableArray *gestureRecognizers = [NSMutableArray array]; + [gestureRecognizers addObject:tapGesture]; + [gestureRecognizers addObjectsFromArray:scnView.gestureRecognizers]; + scnView.gestureRecognizers = gestureRecognizers; + + return tapGesture; + return nil; +} + +@end diff --git a/extensions/objective-c/test/colorize-results/test_m.json b/extensions/objective-c/test/colorize-results/test_m.json index 9a4926acad5..0cecfd6f39c 100644 --- a/extensions/objective-c/test/colorize-results/test_m.json +++ b/extensions/objective-c/test/colorize-results/test_m.json @@ -1,7 +1,7 @@ [ { "c": "//", - "t": "source.objc comment.line.double-slash.cpp punctuation.definition.comment.cpp", + "t": "source.objc comment.line.double-slash.objc punctuation.definition.comment.objc", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -12,7 +12,7 @@ }, { "c": "//", - "t": "source.objc comment.line.double-slash.cpp punctuation.definition.comment.cpp", + "t": "source.objc comment.line.double-slash.objc punctuation.definition.comment.objc", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -23,7 +23,7 @@ }, { "c": " Copyright (c) Microsoft Corporation. All rights reserved.", - "t": "source.objc comment.line.double-slash.cpp", + "t": "source.objc comment.line.double-slash.objc", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -34,7 +34,7 @@ }, { "c": "//", - "t": "source.objc comment.line.double-slash.cpp punctuation.definition.comment.cpp", + "t": "source.objc comment.line.double-slash.objc punctuation.definition.comment.objc", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -45,7 +45,7 @@ }, { "c": "#", - "t": "source.objc meta.preprocessor.include.c keyword.control.directive.import.c punctuation.definition.directive.c", + "t": "source.objc meta.preprocessor.include.objc keyword.control.directive.import.objc punctuation.definition.directive.objc", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -56,7 +56,7 @@ }, { "c": "import", - "t": "source.objc meta.preprocessor.include.c keyword.control.directive.import.c", + "t": "source.objc meta.preprocessor.include.objc keyword.control.directive.import.objc", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -67,7 +67,7 @@ }, { "c": " ", - "t": "source.objc meta.preprocessor.include.c", + "t": "source.objc meta.preprocessor.include.objc", "r": { "dark_plus": "meta.preprocessor: #569CD6", "light_plus": "meta.preprocessor: #0000FF", @@ -78,7 +78,7 @@ }, { "c": "\"", - "t": "source.objc meta.preprocessor.include.c string.quoted.double.include.c punctuation.definition.string.begin.c", + "t": "source.objc meta.preprocessor.include.objc string.quoted.double.include.objc punctuation.definition.string.begin.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -89,7 +89,7 @@ }, { "c": "UseQuotes.h", - "t": "source.objc meta.preprocessor.include.c string.quoted.double.include.c", + "t": "source.objc meta.preprocessor.include.objc string.quoted.double.include.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -100,7 +100,7 @@ }, { "c": "\"", - "t": "source.objc meta.preprocessor.include.c string.quoted.double.include.c punctuation.definition.string.end.c", + "t": "source.objc meta.preprocessor.include.objc string.quoted.double.include.objc punctuation.definition.string.end.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -111,7 +111,7 @@ }, { "c": "#", - "t": "source.objc meta.preprocessor.include.c keyword.control.directive.import.c punctuation.definition.directive.c", + "t": "source.objc meta.preprocessor.include.objc keyword.control.directive.import.objc punctuation.definition.directive.objc", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -122,7 +122,7 @@ }, { "c": "import", - "t": "source.objc meta.preprocessor.include.c keyword.control.directive.import.c", + "t": "source.objc meta.preprocessor.include.objc keyword.control.directive.import.objc", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -133,7 +133,7 @@ }, { "c": " ", - "t": "source.objc meta.preprocessor.include.c", + "t": "source.objc meta.preprocessor.include.objc", "r": { "dark_plus": "meta.preprocessor: #569CD6", "light_plus": "meta.preprocessor: #0000FF", @@ -144,7 +144,7 @@ }, { "c": "<", - "t": "source.objc meta.preprocessor.include.c string.quoted.other.lt-gt.include.c punctuation.definition.string.begin.c", + "t": "source.objc meta.preprocessor.include.objc string.quoted.other.lt-gt.include.objc punctuation.definition.string.begin.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -155,7 +155,7 @@ }, { "c": "Use/GTLT.h", - "t": "source.objc meta.preprocessor.include.c string.quoted.other.lt-gt.include.c", + "t": "source.objc meta.preprocessor.include.objc string.quoted.other.lt-gt.include.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -166,7 +166,7 @@ }, { "c": ">", - "t": "source.objc meta.preprocessor.include.c string.quoted.other.lt-gt.include.c punctuation.definition.string.end.c", + "t": "source.objc meta.preprocessor.include.objc string.quoted.other.lt-gt.include.objc punctuation.definition.string.end.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -177,7 +177,7 @@ }, { "c": "/*", - "t": "source.objc comment.block.c punctuation.definition.comment.begin.c", + "t": "source.objc comment.block.objc punctuation.definition.comment.begin.objc", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -188,7 +188,7 @@ }, { "c": "\tMulti", - "t": "source.objc comment.block.c", + "t": "source.objc comment.block.objc", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -199,7 +199,7 @@ }, { "c": "\tLine", - "t": "source.objc comment.block.c", + "t": "source.objc comment.block.objc", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -210,7 +210,7 @@ }, { "c": "\tComments", - "t": "source.objc comment.block.c", + "t": "source.objc comment.block.objc", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -221,7 +221,7 @@ }, { "c": "*/", - "t": "source.objc comment.block.c punctuation.definition.comment.end.c", + "t": "source.objc comment.block.objc punctuation.definition.comment.end.objc", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -298,7 +298,7 @@ }, { "c": "void", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.function.objc meta.return-type.objc storage.type.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.function.objc meta.return-type.objc storage.type.built-in.primitive.objc", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -364,7 +364,7 @@ }, { "c": "NSNotification", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.function.objc meta.argument-type.objc support.class.cocoa", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.function.objc meta.argument-type.objc support.class.cocoa.objc", "r": { "dark_plus": "support.class: #4EC9B0", "light_plus": "support.class: #267F99", @@ -386,7 +386,7 @@ }, { "c": "*", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.function.objc meta.argument-type.objc keyword.operator.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.function.objc meta.argument-type.objc keyword.operator.objc", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -419,7 +419,7 @@ }, { "c": "{", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.block.begin.bracket.curly.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.section.block.begin.bracket.curly.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -430,7 +430,7 @@ }, { "c": "}", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.block.end.bracket.curly.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.section.block.end.bracket.curly.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -551,7 +551,7 @@ }, { "c": "{", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.block.begin.bracket.curly.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.section.block.begin.bracket.curly.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -562,7 +562,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -573,7 +573,7 @@ }, { "c": "NSString", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c support.class.cocoa", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc support.class.cocoa.objc", "r": { "dark_plus": "support.class: #4EC9B0", "light_plus": "support.class: #267F99", @@ -584,7 +584,7 @@ }, { "c": "*", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.objc", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -595,7 +595,7 @@ }, { "c": " defaultDir ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -606,7 +606,7 @@ }, { "c": "=", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.assignment.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.assignment.objc", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -617,7 +617,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.whitespace.support.function.leading.cocoa", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.whitespace.support.function.leading.cocoa.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -628,7 +628,7 @@ }, { "c": "NSSearchPathForDirectoriesInDomains", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c support.function.cocoa", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc support.function.cocoa.objc", "r": { "dark_plus": "support.function: #DCDCAA", "light_plus": "support.function: #795E26", @@ -639,7 +639,7 @@ }, { "c": "(", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.parens.begin.bracket.round.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.parens.block.objc punctuation.section.parens.begin.bracket.round.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -650,7 +650,7 @@ }, { "c": "NSDocumentDirectory", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c support.constant.cocoa", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.parens.block.objc support.constant.cocoa.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -661,7 +661,7 @@ }, { "c": ",", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.separator.delimiter.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.parens.block.objc punctuation.separator.delimiter.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -672,7 +672,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.parens.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -683,7 +683,7 @@ }, { "c": "NSUserDomainMask", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c support.constant.cocoa", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.parens.block.objc support.constant.cocoa.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -694,7 +694,7 @@ }, { "c": ",", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.separator.delimiter.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.parens.block.objc punctuation.separator.delimiter.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -705,7 +705,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.parens.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -716,7 +716,7 @@ }, { "c": "true", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c constant.language.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.parens.block.objc constant.language.objc", "r": { "dark_plus": "constant.language: #569CD6", "light_plus": "constant.language: #0000FF", @@ -727,7 +727,7 @@ }, { "c": ")", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.parens.end.bracket.round.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.parens.block.objc punctuation.section.parens.end.bracket.round.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -738,7 +738,7 @@ }, { "c": "[", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.begin.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -749,7 +749,7 @@ }, { "c": "0", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c constant.numeric.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc constant.numeric.decimal.objc", "r": { "dark_plus": "constant.numeric: #B5CEA8", "light_plus": "constant.numeric: #09885A", @@ -760,7 +760,7 @@ }, { "c": "]", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.end.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -771,7 +771,7 @@ }, { "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -782,7 +782,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -793,7 +793,7 @@ }, { "c": "NSOpenPanel", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c support.class.cocoa", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc support.class.cocoa.objc", "r": { "dark_plus": "support.class: #4EC9B0", "light_plus": "support.class: #267F99", @@ -804,7 +804,7 @@ }, { "c": "*", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.objc", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -815,7 +815,7 @@ }, { "c": " panel ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -826,7 +826,7 @@ }, { "c": "=", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.assignment.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.assignment.objc", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -837,7 +837,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -848,7 +848,7 @@ }, { "c": "[", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.begin.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -859,7 +859,7 @@ }, { "c": "NSOpenPanel", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c support.class.cocoa", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc support.class.cocoa.objc", "r": { "dark_plus": "support.class: #4EC9B0", "light_plus": "support.class: #267F99", @@ -870,7 +870,7 @@ }, { "c": " openPanel", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -881,7 +881,7 @@ }, { "c": "]", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.end.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -892,7 +892,7 @@ }, { "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -903,7 +903,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -914,7 +914,7 @@ }, { "c": "[", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.begin.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -925,7 +925,7 @@ }, { "c": "panel setAllowedFileTypes:", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -935,8 +935,19 @@ } }, { - "c": "[[", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.begin.bracket.square.c", + "c": "[", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -947,7 +958,7 @@ }, { "c": "NSArray", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c support.class.cocoa", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc meta.bracket.square.access.objc support.class.cocoa.objc", "r": { "dark_plus": "support.class: #4EC9B0", "light_plus": "support.class: #267F99", @@ -958,7 +969,7 @@ }, { "c": " alloc", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -969,7 +980,7 @@ }, { "c": "]", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.end.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -980,7 +991,7 @@ }, { "c": " initWithObjects:", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -991,7 +1002,7 @@ }, { "c": "@\"", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c string.quoted.double.objc punctuation.definition.string.begin.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc string.quoted.double.objc punctuation.definition.string.begin.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1002,7 +1013,7 @@ }, { "c": "ipa", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c string.quoted.double.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc string.quoted.double.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1013,7 +1024,7 @@ }, { "c": "\"", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c string.quoted.double.objc punctuation.definition.string.end.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc string.quoted.double.objc punctuation.definition.string.end.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1024,7 +1035,7 @@ }, { "c": ",", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.separator.delimiter.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.separator.delimiter.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1035,7 +1046,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1046,7 +1057,7 @@ }, { "c": "@\"", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c string.quoted.double.objc punctuation.definition.string.begin.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc string.quoted.double.objc punctuation.definition.string.begin.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1057,7 +1068,7 @@ }, { "c": "xcarchive", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c string.quoted.double.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc string.quoted.double.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1068,7 +1079,7 @@ }, { "c": "\"", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c string.quoted.double.objc punctuation.definition.string.end.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc string.quoted.double.objc punctuation.definition.string.end.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1079,7 +1090,7 @@ }, { "c": ",", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.separator.delimiter.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.separator.delimiter.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1090,7 +1101,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1101,7 +1112,7 @@ }, { "c": "@\"", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c string.quoted.double.objc punctuation.definition.string.begin.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc string.quoted.double.objc punctuation.definition.string.begin.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1112,7 +1123,7 @@ }, { "c": "app", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c string.quoted.double.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc string.quoted.double.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1123,7 +1134,7 @@ }, { "c": "\"", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c string.quoted.double.objc punctuation.definition.string.end.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc string.quoted.double.objc punctuation.definition.string.end.objc", "r": { "dark_plus": "string: #CE9178", "light_plus": "string: #A31515", @@ -1134,7 +1145,7 @@ }, { "c": ",", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.separator.delimiter.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.separator.delimiter.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1145,7 +1156,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1156,7 +1167,7 @@ }, { "c": "nil", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c constant.language.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc constant.language.objc", "r": { "dark_plus": "constant.language: #569CD6", "light_plus": "constant.language: #0000FF", @@ -1166,393 +1177,8 @@ } }, { - "c": "]]", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.end.bracket.square.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "[", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.begin.bracket.square.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "panel beginWithCompletionHandler:", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "^", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.c", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": "(", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.parens.begin.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "NSInteger", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c support.type.cocoa.leopard", - "r": { - "dark_plus": "support.type: #4EC9B0", - "light_plus": "support.type: #267F99", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "support.type: #4EC9B0" - } - }, - { - "c": " result", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ")", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.parens.end.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "{", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.block.begin.bracket.curly.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "if", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.control.c", - "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", - "dark_vs": "keyword.control: #569CD6", - "light_vs": "keyword.control: #0000FF", - "hc_black": "keyword.control: #C586C0" - } - }, - { - "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "(", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.parens.begin.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "result ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "==", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.comparison.c", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "NSFileHandlingPanelOKButton", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c support.constant.cocoa", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ")", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.parens.end.bracket.round.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "[", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.begin.bracket.square.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "self", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ".", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.separator.dot-access.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "inputTextField", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c variable.other.member.c", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": " setStringValue:", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "[", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.begin.bracket.square.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "panel", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ".", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.separator.dot-access.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "URL", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c variable.other.member.c", - "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "variable: #9CDCFE" - } - }, - { - "c": " path", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "]]", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.end.bracket.square.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "}", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.block.end.bracket.curly.c", + "c": "]", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1563,7 +1189,7 @@ }, { "c": "]", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.end.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1574,7 +1200,95 @@ }, { "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "panel beginWithCompletionHandler:", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "^", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc keyword.operator.objc", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": "(", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.section.parens.begin.bracket.round.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSInteger", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc support.type.cocoa.leopard.objc", + "r": { + "dark_plus": "support.type: #4EC9B0", + "light_plus": "support.type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.type: #4EC9B0" + } + }, + { + "c": " result", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ")", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.section.parens.end.bracket.round.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1585,7 +1299,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1595,8 +1309,30 @@ } }, { - "c": "return", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.control.c", + "c": "{", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.section.block.begin.bracket.curly.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "if", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc keyword.control.objc", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -1607,7 +1343,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1617,19 +1353,217 @@ } }, { - "c": "YES", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c constant.language.objc", + "c": "(", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.parens.block.objc punctuation.section.parens.begin.bracket.round.objc", "r": { - "dark_plus": "constant.language: #569CD6", - "light_plus": "constant.language: #0000FF", - "dark_vs": "constant.language: #569CD6", - "light_vs": "constant.language: #0000FF", - "hc_black": "constant.language: #569CD6" + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "result ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.parens.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "==", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.parens.block.objc keyword.operator.comparison.objc", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.parens.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSFileHandlingPanelOKButton", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.parens.block.objc support.constant.cocoa.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ")", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.parens.block.objc punctuation.section.parens.end.bracket.round.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "self", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc variable.other.object.access.objc", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.separator.dot-access.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "inputTextField", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc variable.other.member.objc", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": " setStringValue:", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "panel", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc meta.bracket.square.access.objc variable.other.object.access.objc", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.separator.dot-access.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "URL", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc meta.bracket.square.access.objc variable.other.member.objc", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": " path", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc meta.bracket.square.access.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" } }, { "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.terminator.statement.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1640,260 +1574,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "int", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c storage.type.c", - "r": { - "dark_plus": "storage.type: #569CD6", - "light_plus": "storage.type: #0000FF", - "dark_vs": "storage.type: #569CD6", - "light_vs": "storage.type: #0000FF", - "hc_black": "storage.type: #569CD6" - } - }, - { - "c": " hex ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "=", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.assignment.c", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "0xFEF1F0F", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c constant.numeric.c", - "r": { - "dark_plus": "constant.numeric: #B5CEA8", - "light_plus": "constant.numeric: #09885A", - "dark_vs": "constant.numeric: #B5CEA8", - "light_vs": "constant.numeric: #09885A", - "hc_black": "constant.numeric: #B5CEA8" - } - }, - { - "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\t ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "float", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c storage.type.c", - "r": { - "dark_plus": "storage.type: #569CD6", - "light_plus": "storage.type: #0000FF", - "dark_vs": "storage.type: #569CD6", - "light_vs": "storage.type: #0000FF", - "hc_black": "storage.type: #569CD6" - } - }, - { - "c": " ing ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "=", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.assignment.c", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "3.14", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c constant.numeric.c", - "r": { - "dark_plus": "constant.numeric: #B5CEA8", - "light_plus": "constant.numeric: #09885A", - "dark_vs": "constant.numeric: #B5CEA8", - "light_vs": "constant.numeric: #09885A", - "hc_black": "constant.numeric: #B5CEA8" - } - }, - { - "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\t ing ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "=", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.assignment.c", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "3.14e0", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c constant.numeric.c", - "r": { - "dark_plus": "constant.numeric: #B5CEA8", - "light_plus": "constant.numeric: #09885A", - "dark_vs": "constant.numeric: #B5CEA8", - "light_vs": "constant.numeric: #09885A", - "hc_black": "constant.numeric: #B5CEA8" - } - }, - { - "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "\t ing ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "=", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.assignment.c", - "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", - "dark_vs": "keyword.operator: #D4D4D4", - "light_vs": "keyword.operator: #000000", - "hc_black": "keyword.operator: #D4D4D4" - } - }, - { - "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "31.4e-2", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c constant.numeric.c", - "r": { - "dark_plus": "constant.numeric: #B5CEA8", - "light_plus": "constant.numeric: #09885A", - "dark_vs": "constant.numeric: #B5CEA8", - "light_vs": "constant.numeric: #09885A", - "hc_black": "constant.numeric: #B5CEA8" - } - }, - { - "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1904,7 +1585,491 @@ }, { "c": "}", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.block.end.bracket.curly.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.section.block.end.bracket.curly.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "return", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.control.objc", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "YES", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.language.objc", + "r": { + "dark_plus": "constant.language: #569CD6", + "light_plus": "constant.language: #0000FF", + "dark_vs": "constant.language: #569CD6", + "light_vs": "constant.language: #0000FF", + "hc_black": "constant.language: #569CD6" + } + }, + { + "c": ";", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "int", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc storage.type.built-in.primitive.objc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " hex ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.assignment.objc", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "0x", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.other.unit.hexadecimal.objc", + "r": { + "dark_plus": "keyword.other.unit: #B5CEA8", + "light_plus": "keyword.other.unit: #09885A", + "dark_vs": "keyword.other.unit: #B5CEA8", + "light_vs": "keyword.other.unit: #09885A", + "hc_black": "keyword.other.unit: #B5CEA8" + } + }, + { + "c": "FEF1F0F", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.hexadecimal.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ";", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\t ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "float", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc storage.type.built-in.primitive.objc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ing ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.assignment.objc", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "3", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.decimal.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ".", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.decimal.point.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": "14", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.decimal.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ";", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\t ing ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.assignment.objc", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "3", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.decimal.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ".", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.decimal.point.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": "14", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.decimal.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": "e", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.other.unit.exponent.decimal.objc", + "r": { + "dark_plus": "keyword.other.unit: #B5CEA8", + "light_plus": "keyword.other.unit: #09885A", + "dark_vs": "keyword.other.unit: #B5CEA8", + "light_vs": "keyword.other.unit: #09885A", + "hc_black": "keyword.other.unit: #B5CEA8" + } + }, + { + "c": "0", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.exponent.decimal.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ";", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\t ing ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.assignment.objc", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "31", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.decimal.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ".", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.decimal.point.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": "4", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.decimal.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": "e", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.other.unit.exponent.decimal.objc", + "r": { + "dark_plus": "keyword.other.unit: #B5CEA8", + "light_plus": "keyword.other.unit: #09885A", + "dark_vs": "keyword.other.unit: #B5CEA8", + "light_vs": "keyword.other.unit: #09885A", + "hc_black": "keyword.other.unit: #B5CEA8" + } + }, + { + "c": "-", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.minus.exponent.decimal.objc", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": "2", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.numeric.exponent.decimal.objc", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ";", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "}", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.section.block.end.bracket.curly.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2201,7 +2366,7 @@ }, { "c": "{", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.block.begin.bracket.curly.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.section.block.begin.bracket.curly.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2212,7 +2377,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.whitespace.comment.leading.cpp", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.whitespace.comment.leading.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2223,7 +2388,7 @@ }, { "c": "//", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c comment.line.double-slash.cpp punctuation.definition.comment.cpp", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc comment.line.double-slash.objc punctuation.definition.comment.objc", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -2234,7 +2399,7 @@ }, { "c": " add a tap gesture recognizer", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c comment.line.double-slash.cpp", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc comment.line.double-slash.objc", "r": { "dark_plus": "comment: #6A9955", "light_plus": "comment: #008000", @@ -2245,7 +2410,7 @@ }, { "c": " UITapGestureRecognizer ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2256,7 +2421,7 @@ }, { "c": "*", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.objc", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -2267,7 +2432,7 @@ }, { "c": "tapGesture ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2278,7 +2443,7 @@ }, { "c": "=", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.assignment.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.assignment.objc", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -2289,7 +2454,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2299,8 +2464,19 @@ } }, { - "c": "[[", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.begin.bracket.square.c", + "c": "[", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2311,7 +2487,7 @@ }, { "c": "UITapGestureRecognizer alloc", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2322,7 +2498,7 @@ }, { "c": "]", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.end.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2333,7 +2509,7 @@ }, { "c": " initWithTarget:self action:", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2344,7 +2520,7 @@ }, { "c": "@", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c meta.selector.objc storage.type.objc punctuation.definition.storage.type.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.selector.objc storage.type.objc punctuation.definition.storage.type.objc", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -2355,7 +2531,7 @@ }, { "c": "selector", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c meta.selector.objc storage.type.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.selector.objc storage.type.objc", "r": { "dark_plus": "storage.type: #569CD6", "light_plus": "storage.type: #0000FF", @@ -2366,7 +2542,7 @@ }, { "c": "(", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c meta.selector.objc punctuation.definition.storage.type.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.selector.objc punctuation.definition.storage.type.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2377,7 +2553,7 @@ }, { "c": "handleTap:", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c meta.selector.objc meta.selector.method-name.objc support.function.any-method.name-of-parameter.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.selector.objc meta.selector.method-name.objc support.function.any-method.name-of-parameter.objc", "r": { "dark_plus": "support.function: #DCDCAA", "light_plus": "support.function: #795E26", @@ -2388,7 +2564,7 @@ }, { "c": ")", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c meta.selector.objc punctuation.definition.storage.type.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc meta.selector.objc punctuation.definition.storage.type.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2399,7 +2575,7 @@ }, { "c": "]", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.end.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2410,7 +2586,7 @@ }, { "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2421,7 +2597,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2432,7 +2608,7 @@ }, { "c": "NSMutableArray", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c support.class.cocoa", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc support.class.cocoa.objc", "r": { "dark_plus": "support.class: #4EC9B0", "light_plus": "support.class: #267F99", @@ -2443,7 +2619,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2454,7 +2630,7 @@ }, { "c": "*", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.objc", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -2465,7 +2641,7 @@ }, { "c": "gestureRecognizers ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2476,7 +2652,7 @@ }, { "c": "=", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.assignment.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.assignment.objc", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -2487,7 +2663,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2498,7 +2674,7 @@ }, { "c": "[", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.begin.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2509,7 +2685,7 @@ }, { "c": "NSMutableArray", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c support.class.cocoa", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc support.class.cocoa.objc", "r": { "dark_plus": "support.class: #4EC9B0", "light_plus": "support.class: #267F99", @@ -2520,7 +2696,7 @@ }, { "c": " array", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2531,7 +2707,7 @@ }, { "c": "]", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.end.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2542,7 +2718,7 @@ }, { "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2553,7 +2729,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2564,7 +2740,7 @@ }, { "c": "[", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.begin.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2575,7 +2751,7 @@ }, { "c": "gestureRecognizers addObject:tapGesture", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2586,7 +2762,7 @@ }, { "c": "]", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.end.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2597,7 +2773,7 @@ }, { "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2608,7 +2784,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2619,7 +2795,7 @@ }, { "c": "[", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.begin.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.begin.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2629,8 +2805,8 @@ } }, { - "c": "gestureRecognizers addObjectsFromArray:scnView", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "c": "gestureRecognizers addObjectsFromArray:", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2639,9 +2815,20 @@ "hc_black": "default: #FFFFFF" } }, + { + "c": "scnView", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc variable.other.object.access.objc", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, { "c": ".", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.separator.dot-access.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.separator.dot-access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2652,7 +2839,7 @@ }, { "c": "gestureRecognizers", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c variable.other.member.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc variable.other.member.objc", "r": { "dark_plus": "variable: #9CDCFE", "light_plus": "variable: #001080", @@ -2663,7 +2850,7 @@ }, { "c": "]", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.definition.end.bracket.square.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracket.square.access.objc punctuation.definition.end.bracket.square.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2674,7 +2861,7 @@ }, { "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2684,8 +2871,8 @@ } }, { - "c": " scnView", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "c": " ", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2694,9 +2881,20 @@ "hc_black": "default: #FFFFFF" } }, + { + "c": "scnView", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc variable.other.object.access.objc", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, { "c": ".", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.separator.dot-access.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.separator.dot-access.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2707,7 +2905,7 @@ }, { "c": "gestureRecognizers", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c variable.other.member.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc variable.other.member.objc", "r": { "dark_plus": "variable: #9CDCFE", "light_plus": "variable: #001080", @@ -2718,7 +2916,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2729,7 +2927,7 @@ }, { "c": "=", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.operator.assignment.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.operator.assignment.objc", "r": { "dark_plus": "keyword.operator: #D4D4D4", "light_plus": "keyword.operator: #000000", @@ -2740,7 +2938,7 @@ }, { "c": " gestureRecognizers", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2751,7 +2949,7 @@ }, { "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2762,7 +2960,7 @@ }, { "c": "\t", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2773,7 +2971,7 @@ }, { "c": "return", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.control.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.control.objc", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -2784,7 +2982,7 @@ }, { "c": " tapGesture", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2795,7 +2993,7 @@ }, { "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2806,7 +3004,7 @@ }, { "c": "\t", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2817,7 +3015,7 @@ }, { "c": "return", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c keyword.control.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.control.objc", "r": { "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", @@ -2828,7 +3026,7 @@ }, { "c": " ", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2839,7 +3037,7 @@ }, { "c": "nil", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c constant.language.objc", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc constant.language.objc", "r": { "dark_plus": "constant.language: #569CD6", "light_plus": "constant.language: #0000FF", @@ -2850,7 +3048,7 @@ }, { "c": ";", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.terminator.statement.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.terminator.statement.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -2861,7 +3059,7 @@ }, { "c": "}", - "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.c punctuation.section.block.end.bracket.curly.c", + "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc punctuation.section.block.end.bracket.curly.objc", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", diff --git a/extensions/objective-c/test/colorize-results/test_mm.json b/extensions/objective-c/test/colorize-results/test_mm.json new file mode 100644 index 00000000000..2af2751bcec --- /dev/null +++ b/extensions/objective-c/test/colorize-results/test_mm.json @@ -0,0 +1,3093 @@ +[ + { + "c": "//", + "t": "source.objcpp comment.line.double-slash.objcpp punctuation.definition.comment.objcpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "//", + "t": "source.objcpp comment.line.double-slash.objcpp punctuation.definition.comment.objcpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " Copyright (c) Microsoft Corporation. All rights reserved.", + "t": "source.objcpp comment.line.double-slash.objcpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "//", + "t": "source.objcpp comment.line.double-slash.objcpp punctuation.definition.comment.objcpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "#", + "t": "source.objcpp meta.preprocessor.include.objcpp keyword.control.directive.import.objcpp punctuation.definition.directive.objcpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": "import", + "t": "source.objcpp meta.preprocessor.include.objcpp keyword.control.directive.import.objcpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": " ", + "t": "source.objcpp meta.preprocessor.include.objcpp", + "r": { + "dark_plus": "meta.preprocessor: #569CD6", + "light_plus": "meta.preprocessor: #0000FF", + "dark_vs": "meta.preprocessor: #569CD6", + "light_vs": "meta.preprocessor: #0000FF", + "hc_black": "meta.preprocessor: #569CD6" + } + }, + { + "c": "\"", + "t": "source.objcpp meta.preprocessor.include.objcpp string.quoted.double.include.objcpp punctuation.definition.string.begin.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "UseQuotes.h", + "t": "source.objcpp meta.preprocessor.include.objcpp string.quoted.double.include.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "\"", + "t": "source.objcpp meta.preprocessor.include.objcpp string.quoted.double.include.objcpp punctuation.definition.string.end.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "#", + "t": "source.objcpp meta.preprocessor.include.objcpp keyword.control.directive.import.objcpp punctuation.definition.directive.objcpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": "import", + "t": "source.objcpp meta.preprocessor.include.objcpp keyword.control.directive.import.objcpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": " ", + "t": "source.objcpp meta.preprocessor.include.objcpp", + "r": { + "dark_plus": "meta.preprocessor: #569CD6", + "light_plus": "meta.preprocessor: #0000FF", + "dark_vs": "meta.preprocessor: #569CD6", + "light_vs": "meta.preprocessor: #0000FF", + "hc_black": "meta.preprocessor: #569CD6" + } + }, + { + "c": "<", + "t": "source.objcpp meta.preprocessor.include.objcpp string.quoted.other.lt-gt.include.objcpp punctuation.definition.string.begin.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "Use/GTLT.h", + "t": "source.objcpp meta.preprocessor.include.objcpp string.quoted.other.lt-gt.include.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": ">", + "t": "source.objcpp meta.preprocessor.include.objcpp string.quoted.other.lt-gt.include.objcpp punctuation.definition.string.end.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "/*", + "t": "source.objcpp comment.block.objcpp punctuation.definition.comment.begin.objcpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "\tMulti", + "t": "source.objcpp comment.block.objcpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "\tLine", + "t": "source.objcpp comment.block.objcpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "\tComments", + "t": "source.objcpp comment.block.objcpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "*/", + "t": "source.objcpp comment.block.objcpp punctuation.definition.comment.end.objcpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "@", + "t": "source.objcpp meta.implementation.objcpp storage.type.objcpp punctuation.definition.storage.type.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "implementation", + "t": "source.objcpp meta.implementation.objcpp storage.type.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "Test", + "t": "source.objcpp meta.implementation.objcpp entity.name.type.objcpp", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": "- ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "(", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp punctuation.definition.type.begin.objcpp", + "r": { + "dark_plus": "meta.return-type: #4EC9B0", + "light_plus": "meta.return-type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "meta.return-type: #4EC9B0" + } + }, + { + "c": "void", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp storage.type.built-in.primitive.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": ")", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp punctuation.definition.type.end.objcpp", + "r": { + "dark_plus": "meta.return-type: #4EC9B0", + "light_plus": "meta.return-type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "meta.return-type: #4EC9B0" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp", + "r": { + "dark_plus": "meta.return-type: #4EC9B0", + "light_plus": "meta.return-type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "meta.return-type: #4EC9B0" + } + }, + { + "c": "applicationWillFinishLaunching", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp entity.name.function.objcpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": ":", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp entity.name.function.name-of-parameter.objcpp punctuation.separator.arguments.objcpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": "(", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp punctuation.definition.type.begin.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSNotification", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp support.class.cocoa.objcpp", + "r": { + "dark_plus": "support.class: #4EC9B0", + "light_plus": "support.class: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.class: #4EC9B0" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "*", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp keyword.operator.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": ")", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp punctuation.definition.type.end.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "notification", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp variable.parameter.function.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": "{", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.section.block.begin.bracket.curly.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "}", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.section.block.end.bracket.curly.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "- ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "(", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp punctuation.definition.type.begin.objcpp", + "r": { + "dark_plus": "meta.return-type: #4EC9B0", + "light_plus": "meta.return-type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "meta.return-type: #4EC9B0" + } + }, + { + "c": "IBAction", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp storage.type.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": ")", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp punctuation.definition.type.end.objcpp", + "r": { + "dark_plus": "meta.return-type: #4EC9B0", + "light_plus": "meta.return-type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "meta.return-type: #4EC9B0" + } + }, + { + "c": "onSelectInput", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp entity.name.function.objcpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": ":", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp entity.name.function.name-of-parameter.objcpp punctuation.separator.arguments.objcpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": "(", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp punctuation.definition.type.begin.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "id", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp storage.type.id.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": ")", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp punctuation.definition.type.end.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "sender", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp variable.parameter.function.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": "{", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.section.block.begin.bracket.curly.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSString", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp support.class.cocoa.objcpp", + "r": { + "dark_plus": "support.class: #4EC9B0", + "light_plus": "support.class: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.class: #4EC9B0" + } + }, + { + "c": "*", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " defaultDir ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.assignment.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.whitespace.support.function.leading.cocoa.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSSearchPathForDirectoriesInDomains", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp support.function.cocoa.objcpp", + "r": { + "dark_plus": "support.function: #DCDCAA", + "light_plus": "support.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.function: #DCDCAA" + } + }, + { + "c": "(", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.parens.block.objcpp punctuation.section.parens.begin.bracket.round.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSDocumentDirectory", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.parens.block.objcpp support.constant.cocoa.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ",", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.parens.block.objcpp punctuation.separator.delimiter.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.parens.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSUserDomainMask", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.parens.block.objcpp support.constant.cocoa.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ",", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.parens.block.objcpp punctuation.separator.delimiter.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.parens.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "true", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.parens.block.objcpp constant.language.objcpp", + "r": { + "dark_plus": "constant.language: #569CD6", + "light_plus": "constant.language: #0000FF", + "dark_vs": "constant.language: #569CD6", + "light_vs": "constant.language: #0000FF", + "hc_black": "constant.language: #569CD6" + } + }, + { + "c": ")", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.parens.block.objcpp punctuation.section.parens.end.bracket.round.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "0", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp constant.numeric.decimal.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSOpenPanel", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp support.class.cocoa.objcpp", + "r": { + "dark_plus": "support.class: #4EC9B0", + "light_plus": "support.class: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.class: #4EC9B0" + } + }, + { + "c": "*", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " panel ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.assignment.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSOpenPanel", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp support.class.cocoa.objcpp", + "r": { + "dark_plus": "support.class: #4EC9B0", + "light_plus": "support.class: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.class: #4EC9B0" + } + }, + { + "c": " openPanel", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "panel setAllowedFileTypes:", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSArray", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp support.class.cocoa.objcpp", + "r": { + "dark_plus": "support.class: #4EC9B0", + "light_plus": "support.class: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.class: #4EC9B0" + } + }, + { + "c": " alloc", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " initWithObjects:", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "@\"", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp string.quoted.double.objcpp punctuation.definition.string.begin.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "ipa", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp string.quoted.double.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "\"", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp string.quoted.double.objcpp punctuation.definition.string.end.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": ",", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.separator.delimiter.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "@\"", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp string.quoted.double.objcpp punctuation.definition.string.begin.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "xcarchive", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp string.quoted.double.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "\"", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp string.quoted.double.objcpp punctuation.definition.string.end.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": ",", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.separator.delimiter.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "@\"", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp string.quoted.double.objcpp punctuation.definition.string.begin.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "app", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp string.quoted.double.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": "\"", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp string.quoted.double.objcpp punctuation.definition.string.end.objcpp", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178" + } + }, + { + "c": ",", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.separator.delimiter.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "nil", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp constant.language.objcpp", + "r": { + "dark_plus": "constant.language: #569CD6", + "light_plus": "constant.language: #0000FF", + "dark_vs": "constant.language: #569CD6", + "light_vs": "constant.language: #0000FF", + "hc_black": "constant.language: #569CD6" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "panel beginWithCompletionHandler:", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "^", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp keyword.operator.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": "(", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.section.parens.begin.bracket.round.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSInteger", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp support.type.cocoa.leopard.objcpp", + "r": { + "dark_plus": "support.type: #4EC9B0", + "light_plus": "support.type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.type: #4EC9B0" + } + }, + { + "c": " result", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ")", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.section.parens.end.bracket.round.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "{", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.section.block.begin.bracket.curly.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "if", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp keyword.control.objcpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "(", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.parens.block.objcpp punctuation.section.parens.begin.bracket.round.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "result ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.parens.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "==", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.parens.block.objcpp keyword.operator.comparison.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.parens.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSFileHandlingPanelOKButton", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.parens.block.objcpp support.constant.cocoa.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ")", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.parens.block.objcpp punctuation.section.parens.end.bracket.round.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "self", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp variable.other.object.access.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.separator.dot-access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "inputTextField", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp variable.other.member.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": " setStringValue:", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "panel", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp variable.other.object.access.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.separator.dot-access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "URL", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp variable.other.member.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": " path", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "}", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.section.block.end.bracket.curly.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "return", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.control.objcpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "YES", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.language.objcpp", + "r": { + "dark_plus": "constant.language: #569CD6", + "light_plus": "constant.language: #0000FF", + "dark_vs": "constant.language: #569CD6", + "light_vs": "constant.language: #0000FF", + "hc_black": "constant.language: #569CD6" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "int", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp storage.type.built-in.primitive.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " hex ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.assignment.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "0x", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.other.unit.hexadecimal.objcpp", + "r": { + "dark_plus": "keyword.other.unit: #B5CEA8", + "light_plus": "keyword.other.unit: #09885A", + "dark_vs": "keyword.other.unit: #B5CEA8", + "light_vs": "keyword.other.unit: #09885A", + "hc_black": "keyword.other.unit: #B5CEA8" + } + }, + { + "c": "FEF1F0F", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.hexadecimal.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\t ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "float", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp storage.type.built-in.primitive.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ing ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.assignment.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "3", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.decimal.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ".", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.decimal.point.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": "14", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.decimal.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\t ing ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.assignment.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "3", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.decimal.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ".", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.decimal.point.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": "14", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.decimal.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": "e", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.other.unit.exponent.decimal.objcpp", + "r": { + "dark_plus": "keyword.other.unit: #B5CEA8", + "light_plus": "keyword.other.unit: #09885A", + "dark_vs": "keyword.other.unit: #B5CEA8", + "light_vs": "keyword.other.unit: #09885A", + "hc_black": "keyword.other.unit: #B5CEA8" + } + }, + { + "c": "0", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.exponent.decimal.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\t ing ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.assignment.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "31", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.decimal.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ".", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.decimal.point.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": "4", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.decimal.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": "e", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.other.unit.exponent.decimal.objcpp", + "r": { + "dark_plus": "keyword.other.unit: #B5CEA8", + "light_plus": "keyword.other.unit: #09885A", + "dark_vs": "keyword.other.unit: #B5CEA8", + "light_vs": "keyword.other.unit: #09885A", + "hc_black": "keyword.other.unit: #B5CEA8" + } + }, + { + "c": "-", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.minus.exponent.decimal.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": "2", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.numeric.exponent.decimal.objcpp", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "}", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.section.block.end.bracket.curly.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "-", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "(", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp punctuation.definition.type.begin.objcpp", + "r": { + "dark_plus": "meta.return-type: #4EC9B0", + "light_plus": "meta.return-type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "meta.return-type: #4EC9B0" + } + }, + { + "c": "id", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp storage.type.id.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": ")", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp punctuation.definition.type.end.objcpp", + "r": { + "dark_plus": "meta.return-type: #4EC9B0", + "light_plus": "meta.return-type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "meta.return-type: #4EC9B0" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp", + "r": { + "dark_plus": "meta.return-type: #4EC9B0", + "light_plus": "meta.return-type: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "meta.return-type: #4EC9B0" + } + }, + { + "c": "initWithParams", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.return-type.objcpp entity.name.function.objcpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": ":", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp entity.name.function.name-of-parameter.objcpp punctuation.separator.arguments.objcpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": "(", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp punctuation.definition.type.begin.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "id", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp meta.id-with-protocol.objcpp storage.type.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "<", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp meta.id-with-protocol.objcpp meta.protocol-list.objcpp punctuation.section.scope.begin.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "anObject", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp meta.id-with-protocol.objcpp meta.protocol-list.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ">", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp meta.id-with-protocol.objcpp meta.protocol-list.objcpp punctuation.section.scope.end.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ")", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp punctuation.definition.type.end.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "aHandler", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp variable.parameter.function.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "withDeviceStateManager", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp entity.name.function.name-of-parameter.objcpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": ":", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp entity.name.function.name-of-parameter.objcpp punctuation.separator.arguments.objcpp", + "r": { + "dark_plus": "entity.name.function: #DCDCAA", + "light_plus": "entity.name.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "entity.name.function: #DCDCAA" + } + }, + { + "c": "(", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp punctuation.definition.type.begin.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "id", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp meta.id-with-protocol.objcpp storage.type.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "<", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp meta.id-with-protocol.objcpp meta.protocol-list.objcpp punctuation.section.scope.begin.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "anotherObject", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp meta.id-with-protocol.objcpp meta.protocol-list.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ">", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp meta.id-with-protocol.objcpp meta.protocol-list.objcpp punctuation.section.scope.end.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ")", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp punctuation.definition.type.end.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "deviceStateManager", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.function.objcpp meta.argument-type.objcpp variable.parameter.function.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": "{", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.section.block.begin.bracket.curly.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.whitespace.comment.leading.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "//", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp comment.line.double-slash.objcpp punctuation.definition.comment.objcpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " add a tap gesture recognizer", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp comment.line.double-slash.objcpp", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " UITapGestureRecognizer ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "*", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": "tapGesture ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.assignment.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "UITapGestureRecognizer alloc", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " initWithTarget:self action:", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "@", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.selector.objcpp storage.type.objcpp punctuation.definition.storage.type.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "selector", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.selector.objcpp storage.type.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "(", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.selector.objcpp punctuation.definition.storage.type.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "handleTap:", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.selector.objcpp meta.selector.method-name.objcpp support.function.any-method.name-of-parameter.objcpp", + "r": { + "dark_plus": "support.function: #DCDCAA", + "light_plus": "support.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.function: #DCDCAA" + } + }, + { + "c": ")", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp meta.selector.objcpp punctuation.definition.storage.type.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSMutableArray", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp support.class.cocoa.objcpp", + "r": { + "dark_plus": "support.class: #4EC9B0", + "light_plus": "support.class: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.class: #4EC9B0" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "*", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": "gestureRecognizers ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.assignment.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "NSMutableArray", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp support.class.cocoa.objcpp", + "r": { + "dark_plus": "support.class: #4EC9B0", + "light_plus": "support.class: #267F99", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.class: #4EC9B0" + } + }, + { + "c": " array", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "gestureRecognizers addObject:tapGesture", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "[", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.begin.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "gestureRecognizers addObjectsFromArray:", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "scnView", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp variable.other.object.access.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.separator.dot-access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "gestureRecognizers", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp variable.other.member.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": "]", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp punctuation.definition.end.bracket.square.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "scnView", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp variable.other.object.access.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.separator.dot-access.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "gestureRecognizers", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp variable.other.member.objcpp", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.operator.assignment.objcpp", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " gestureRecognizers", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\t", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "return", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.control.objcpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": " tapGesture", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "\t", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "return", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.control.objcpp", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0" + } + }, + { + "c": " ", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "nil", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp constant.language.objcpp", + "r": { + "dark_plus": "constant.language: #569CD6", + "light_plus": "constant.language: #0000FF", + "dark_vs": "constant.language: #569CD6", + "light_vs": "constant.language: #0000FF", + "hc_black": "constant.language: #569CD6" + } + }, + { + "c": ";", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.terminator.statement.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "}", + "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp punctuation.section.block.end.bracket.curly.objcpp", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "@", + "t": "source.objcpp meta.implementation.objcpp storage.type.objcpp punctuation.definition.storage.type.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "end", + "t": "source.objcpp meta.implementation.objcpp storage.type.objcpp", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + } +] \ No newline at end of file diff --git a/extensions/package.json b/extensions/package.json index 9d944cd3ec7..52ece5e2051 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "3.3.0-dev.20190101" + "typescript": "3.5.2" }, "scripts": { "postinstall": "node ./postinstall" diff --git a/extensions/perl/cgmanifest.json b/extensions/perl/cgmanifest.json index 6338921e75f..83d91107671 100644 --- a/extensions/perl/cgmanifest.json +++ b/extensions/perl/cgmanifest.json @@ -30,4 +30,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/perl/package.json b/extensions/perl/package.json index e8dfd7eac69..5676e219fc3 100644 --- a/extensions/perl/package.json +++ b/extensions/perl/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js textmate/perl.tmbundle Syntaxes/Perl.plist ./syntaxes/perl.tmLanguage.json Syntaxes/Perl%206.tmLanguage ./syntaxes/perl6.tmLanguage.json" diff --git a/extensions/php-language-features/package.json b/extensions/php-language-features/package.json index fb6beb6deb5..8172c6bece8 100644 --- a/extensions/php-language-features/package.json +++ b/extensions/php-language-features/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "icon": "icons/logo.png", "engines": { "vscode": "0.10.x" @@ -37,7 +38,8 @@ "null" ], "default": null, - "description": "%configuration.validate.executablePath%" + "description": "%configuration.validate.executablePath%", + "scope": "machine" }, "php.validate.run": { "type": "string", @@ -80,6 +82,6 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^8.10.25" + "@types/node": "^10.14.8" } } diff --git a/extensions/php-language-features/src/features/phpGlobalFunctions.ts b/extensions/php-language-features/src/features/phpGlobalFunctions.ts index b908cb6614a..ce2acbc4258 100644 --- a/extensions/php-language-features/src/features/phpGlobalFunctions.ts +++ b/extensions/php-language-features/src/features/phpGlobalFunctions.ts @@ -191,6 +191,10 @@ export const globalfunctions: IEntries = { description: 'Reclaims memory used by the Zend Engine memory manager', signature: '(void): int' }, + gc_status: { + description: 'Gets information about the garbage collector', + signature: '(void): array' + }, get_cfg_var: { description: 'Gets the value of a PHP configuration option', signature: '( string $option ): mixed' @@ -1036,7 +1040,7 @@ export const globalfunctions: IEntries = { signature: '( string $client_keypair , string $server_key ): array' }, sodium_crypto_kx_keypair: { - description: 'Description', + description: 'Creates a new sodium keypair', signature: '(void): string' }, sodium_crypto_kx_publickey: { @@ -1072,11 +1076,11 @@ export const globalfunctions: IEntries = { signature: '( string $password , int $opslimit , int $memlimit ): bool' }, sodium_crypto_pwhash_str_verify: { - description: 'Verify that hash is a valid password verification string', + description: 'Verifies that a password matches a hash', signature: '( string $hash , string $password ): bool' }, sodium_crypto_pwhash_str: { - description: 'Get an ASCII encoded hash', + description: 'Get an ASCII-encoded hash', signature: '( string $password , int $opslimit , int $memlimit ): string' }, sodium_crypto_pwhash: { @@ -1136,7 +1140,7 @@ export const globalfunctions: IEntries = { }, sodium_crypto_sign_detached: { description: 'Sign the message', - signature: '( string $msg , string $keypair ): string' + signature: '( string $msg , string $secretkey ): string' }, sodium_crypto_sign_ed25519_pk_to_curve25519: { description: 'Convert an Ed25519 public key to a Curve25519 public key', @@ -1156,7 +1160,7 @@ export const globalfunctions: IEntries = { }, sodium_crypto_sign_open: { description: 'Check that the signed message has a valid signature', - signature: '( string $string , string $keypair ): string' + signature: '( string $string , string $public_key ): string' }, sodium_crypto_sign_publickey_from_secretkey: { description: 'Extract the public key from the secret key', @@ -1176,7 +1180,7 @@ export const globalfunctions: IEntries = { }, sodium_crypto_sign_verify_detached: { description: 'Verify signature for the message', - signature: '( string $signature , string $msg , string $key ): bool' + signature: '( string $signature , string $msg , string $public_key ): bool' }, sodium_crypto_sign: { description: 'Sign a message', @@ -1195,7 +1199,7 @@ export const globalfunctions: IEntries = { signature: '( int $length , string $nonce , string $key ): string' }, sodium_hex2bin: { - description: 'Decode from hexadecimal', + description: 'Decodes a hexadecimally encoded binary string', signature: '( string $hex [, string $ignore ]): string' }, sodium_increment: { @@ -1440,7 +1444,7 @@ export const globalfunctions: IEntries = { }, timezone_offset_get: { description: 'Returns the timezone offset from GMT', - signature: '( DateTime $datetime , DateTimeZone $object ): int' + signature: '( DateTimeInterface $datetime , DateTimeZone $object ): int' }, timezone_transitions_get: { description: 'Returns all transitions for the timezone', @@ -1695,7 +1699,7 @@ export const globalfunctions: IEntries = { signature: '( string $filename [, bool $use_include_path [, resource $context [, int $offset = 0 [, int $maxlen ]]]]): string' }, file_put_contents: { - description: 'Write a string to a file', + description: 'Write data to a file', signature: '( string $filename , mixed $data [, int $flags = 0 [, resource $context ]]): int' }, file: { @@ -2317,7 +2321,7 @@ export const globalfunctions: IEntries = { }, datefmt_set_timezone: { description: 'Sets formatterʼs timezone', - signature: '( mixed $zone ): bool' + signature: '( mixed $zone , IntlDateFormatter $fmt ): bool' }, resourcebundle_count: { description: 'Get number of elements in the bundle', @@ -2371,6 +2375,14 @@ export const globalfunctions: IEntries = { description: 'Transliterate a string', signature: '( string $subject [, int $start [, int $end , mixed $transliterator ]]): string' }, + intl_get_error_code: { + description: 'Get the last error code', + signature: '(void): int' + }, + intl_get_error_message: { + description: 'Get description of the last error', + signature: '(void): string' + }, grapheme_extract: { description: 'Function to extract a sequence of default grapheme clusters from a text buffer, which must be encoded in UTF-8', signature: '( string $haystack , int $size [, int $extract_type [, int $start = 0 [, int $next ]]]): string' @@ -2409,24 +2421,16 @@ export const globalfunctions: IEntries = { }, idn_to_ascii: { description: 'Convert domain name to IDNA ASCII form', - signature: '( string $domain [, int $options = IDNA_DEFAULT [, int $variant = INTL_IDNA_VARIANT_2003 [, array $idna_info ]]]): string' + signature: '( string $domain [, int $options = IDNA_DEFAULT [, int $variant = INTL_IDNA_VARIANT_UTS46 [, array $idna_info ]]]): string' }, idn_to_utf8: { description: 'Convert domain name from IDNA ASCII to Unicode', - signature: '( string $domain [, int $options = IDNA_DEFAULT [, int $variant = INTL_IDNA_VARIANT_2003 [, array $idna_info ]]]): string' + signature: '( string $domain [, int $options = IDNA_DEFAULT [, int $variant = INTL_IDNA_VARIANT_UTS46 [, array $idna_info ]]]): string' }, intl_error_name: { description: 'Get symbolic name for a given error code', signature: '( int $error_code ): string' }, - intl_get_error_code: { - description: 'Get the last error code', - signature: '(void): int' - }, - intl_get_error_message: { - description: 'Get description of the last error', - signature: '(void): string' - }, intl_is_failure: { description: 'Check whether the given error code indicates failure', signature: '( int $error_code ): bool' @@ -2488,7 +2492,7 @@ export const globalfunctions: IEntries = { signature: '( string $pattern , string $string [, string $option = "msr" ]): bool' }, mb_ereg_replace_callback: { - description: 'Perform a regular expresssion seach and replace with multibyte support using a callback', + description: 'Perform a regular expression search and replace with multibyte support using a callback', signature: '( string $pattern , callable $callback , string $string [, string $option = "msr" ]): string' }, mb_ereg_replace: { @@ -2704,7 +2708,7 @@ export const globalfunctions: IEntries = { }, bcmod: { description: 'Get modulus of an arbitrary precision number', - signature: '( string $dividend , string $modulus [, int $scale ]): string' + signature: '( string $dividend , string $divisor [, int $scale = 0 ]): string' }, bcmul: { description: 'Multiply two arbitrary precision numbers', @@ -2719,8 +2723,8 @@ export const globalfunctions: IEntries = { signature: '( string $base , string $exponent , string $modulus [, int $scale = 0 ]): string' }, bcscale: { - description: 'Set default scale parameter for all bc math functions', - signature: '([ int $scale ]): int' + description: 'Set or get default scale parameter for all bc math functions', + signature: '( int $scale ): int' }, bcsqrt: { description: 'Get the square root of an arbitrary precision number', @@ -2860,11 +2864,11 @@ export const globalfunctions: IEntries = { }, max: { description: 'Find highest value', - signature: '( array $values , mixed $value1 , mixed $value2 [, mixed $... ]): string' + signature: '( array $values , mixed $value1 [, mixed $... ]): string' }, min: { description: 'Find lowest value', - signature: '( array $values , mixed $value1 , mixed $value2 [, mixed $... ]): string' + signature: '( array $values , mixed $value1 [, mixed $... ]): string' }, mt_getrandmax: { description: 'Show largest possible random value', @@ -3371,13 +3375,17 @@ export const globalfunctions: IEntries = { description: 'Syntax highlighting of a string', signature: '( string $str [, bool $return ]): mixed' }, + hrtime: { + description: 'Get the system\'s high resolution time', + signature: '([ bool $get_as_number ]): mixed' + }, ignore_user_abort: { description: 'Set whether a client disconnect should abort script execution', signature: '([ bool $value ]): int' }, pack: { description: 'Pack data into binary string', - signature: '( string $format [, mixed $args [, mixed $... ]]): string' + signature: '( string $format [, mixed $... ]): string' }, php_check_syntax: { description: 'Check the PHP syntax of (and execute) the specified file', @@ -3403,6 +3411,10 @@ export const globalfunctions: IEntries = { description: 'Set process codepage', signature: '( int $cp ): bool' }, + sapi_windows_vt100_support: { + description: 'Get or set VT100 support for the specified stream associated to an output buffer of a Windows console.', + signature: '( resource $stream [, bool $enable ]): bool' + }, show_source: { description: 'Alias of highlight_file', }, @@ -3545,10 +3557,6 @@ export const globalfunctions: IEntries = { description: 'Copies data from one stream to another', signature: '( resource $source , resource $dest [, int $maxlength = -1 [, int $offset = 0 ]]): int' }, - stream_encoding: { - description: 'Set character set for stream encoding', - signature: '( resource $stream [, string $encoding ]): bool' - }, stream_filter_append: { description: 'Attach a filter to a stream', signature: '( resource $stream , string $filtername [, int $read_write [, mixed $params ]]): resource' @@ -3701,7 +3709,7 @@ export const globalfunctions: IEntries = { signature: '( string $data ): string' }, get_headers: { - description: 'Fetches all the headers sent by the server in response to a HTTP request', + description: 'Fetches all the headers sent by the server in response to an HTTP request', signature: '( string $url [, int $format = 0 [, resource $context ]]): array' }, get_meta_tags: { @@ -3756,6 +3764,10 @@ export const globalfunctions: IEntries = { description: 'Perform a cURL session', signature: '( resource $ch ): mixed' }, + curl_file_create: { + description: 'Create a CURLFile object', + signature: '( string $filename [, string $mimetype [, string $postname ]]): CURLFile' + }, curl_getinfo: { description: 'Get information regarding a specific transfer', signature: '( resource $ch [, int $opt ]): mixed' @@ -3856,16 +3868,12 @@ export const globalfunctions: IEntries = { description: 'Gets cURL version information', signature: '([ int $age = CURLVERSION_NOW ]): array' }, - curl_file_create: { - description: 'Create a CURLFile object', - signature: '( string $filename [, string $mimetype [, string $postname ]]): CURLFile' - }, ftp_alloc: { description: 'Allocates space for a file to be uploaded', signature: '( resource $ftp_stream , int $filesize [, string $result ]): bool' }, ftp_append: { - description: 'Append content of a file a another file on the FTP server', + description: 'Append the contents of a file to another file on the FTP server', signature: '( resource $ftp , string $remote_file , string $local_file [, int $mode ]): bool' }, ftp_cdup: { @@ -4115,11 +4123,11 @@ export const globalfunctions: IEntries = { }, setcookie: { description: 'Send a cookie', - signature: '( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure [, bool $httponly ]]]]]]): bool' + signature: '( string $name [, string $value = "" [, int $expires = 0 [, string $path = "" [, string $domain = "" [, bool $secure [, bool $httponly [, array $options = [] ]]]]]]]): bool' }, setrawcookie: { description: 'Send a cookie without urlencoding the cookie value', - signature: '( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure [, bool $httponly ]]]]]]): bool' + signature: '( string $name [, string $value [, int $expires = 0 [, string $path [, string $domain [, bool $secure [, bool $httponly [, array $options = [] ]]]]]]]): bool' }, socket_get_status: { description: 'Alias of stream_get_meta_data', @@ -4231,7 +4239,7 @@ export const globalfunctions: IEntries = { }, socket_recvmsg: { description: 'Read a message', - signature: '( resource $socket , string $message [, int $flags = 0 ]): int' + signature: '( resource $socket , array $message [, int $flags = 0 ]): int' }, socket_select: { description: 'Runs the select() system call on the given arrays of sockets with a specified timeout', @@ -4413,7 +4421,7 @@ export const globalfunctions: IEntries = { }, session_set_cookie_params: { description: 'Set the session cookie parameters', - signature: '( int $lifetime [, string $path [, string $domain [, bool $secure [, bool $httponly ]]]]): bool' + signature: '( int $lifetime [, string $path [, string $domain [, bool $secure [, bool $httponly , array $options ]]]]): bool' }, session_set_save_handler: { description: 'Sets user-level session storage functions', @@ -4495,8 +4503,8 @@ export const globalfunctions: IEntries = { description: 'Alias of rtrim', }, chr: { - description: 'Return a specific character', - signature: '( int $ascii ): string' + description: 'Generate a single-byte string from a number', + signature: '( int $bytevalue ): string' }, chunk_split: { description: 'Split a string into smaller chunks', @@ -4536,7 +4544,7 @@ export const globalfunctions: IEntries = { }, fprintf: { description: 'Write a formatted string to a stream', - signature: '( resource $handle , string $format [, mixed $args [, mixed $... ]]): int' + signature: '( resource $handle , string $format [, mixed $... ]): int' }, get_html_translation_table: { description: 'Returns the translation table used by htmlspecialchars and htmlentities', @@ -4555,7 +4563,7 @@ export const globalfunctions: IEntries = { signature: '( string $data ): string' }, html_entity_decode: { - description: 'Convert all HTML entities to their applicable characters', + description: 'Convert HTML entities to their corresponding characters', signature: '( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get("default_charset") ]]): string' }, htmlentities: { @@ -4622,7 +4630,7 @@ export const globalfunctions: IEntries = { signature: '( float $number , int $decimals = 0 , string $dec_point = "." , string $thousands_sep = "," ): string' }, ord: { - description: 'Return ASCII value of character', + description: 'Convert the first byte of a string to a value between 0 and 255', signature: '( string $string ): int' }, parse_str: { @@ -4635,7 +4643,7 @@ export const globalfunctions: IEntries = { }, printf: { description: 'Output a formatted string', - signature: '( string $format [, mixed $args [, mixed $... ]]): int' + signature: '( string $format [, mixed $... ]): int' }, quoted_printable_decode: { description: 'Convert a quoted-printable string to an 8 bit string', @@ -4675,7 +4683,7 @@ export const globalfunctions: IEntries = { }, sprintf: { description: 'Return a formatted string', - signature: '( string $format [, mixed $args [, mixed $... ]]): string' + signature: '( string $format [, mixed $... ]): string' }, sscanf: { description: 'Parses input from a string according to a format', @@ -4746,7 +4754,7 @@ export const globalfunctions: IEntries = { }, stripos: { description: 'Find the position of the first occurrence of a case-insensitive substring in a string', - signature: '( string $haystack , string $needle [, int $offset = 0 ]): int' + signature: '( string $haystack , mixed $needle [, int $offset = 0 ]): int' }, stripslashes: { description: 'Un-quotes a quoted string', @@ -4794,11 +4802,11 @@ export const globalfunctions: IEntries = { }, strripos: { description: 'Find the position of the last occurrence of a case-insensitive substring in a string', - signature: '( string $haystack , string $needle [, int $offset = 0 ]): int' + signature: '( string $haystack , mixed $needle [, int $offset = 0 ]): int' }, strrpos: { description: 'Find the position of the last occurrence of a substring in a string', - signature: '( string $haystack , string $needle [, int $offset = 0 ]): int' + signature: '( string $haystack , mixed $needle [, int $offset = 0 ]): int' }, strspn: { description: 'Finds the length of the initial segment of a string consisting entirely of characters contained within a given mask', @@ -4948,16 +4956,24 @@ export const globalfunctions: IEntries = { description: 'Checks if the given key or index exists in the array', signature: '( mixed $key , array $array ): bool' }, + array_key_first: { + description: 'Gets the first key of an array', + signature: '( array $array ): mixed' + }, + array_key_last: { + description: 'Gets the last key of an array', + signature: '( array $array ): mixed' + }, array_keys: { description: 'Return all the keys or a subset of the keys of an array', - signature: '( array $array [, mixed $search_value [, bool $strict ]]): array' + signature: '( array $array , mixed $search_value [, bool $strict ]): array' }, array_map: { description: 'Applies the callback to the elements of the given arrays', signature: '( callable $callback , array $array1 [, array $... ]): array' }, array_merge_recursive: { - description: 'Merge two or more arrays recursively', + description: 'Merge one or more arrays recursively', signature: '( array $array1 [, array $... ]): array' }, array_merge: { @@ -4985,7 +5001,7 @@ export const globalfunctions: IEntries = { signature: '( array $array [, mixed $... ]): int' }, array_rand: { - description: 'Pick one or more random entries out of an array', + description: 'Pick one or more random keys out of an array', signature: '( array $array [, int $num = 1 ]): mixed' }, array_reduce: { @@ -4994,11 +5010,11 @@ export const globalfunctions: IEntries = { }, array_replace_recursive: { description: 'Replaces elements from passed arrays into the first array recursively', - signature: '( array $array1 , array $array2 [, array $... ]): array' + signature: '( array $array1 [, array $... ]): array' }, array_replace: { description: 'Replaces elements from passed arrays into the first array', - signature: '( array $array1 , array $array2 [, array $... ]): array' + signature: '( array $array1 [, array $... ]): array' }, array_reverse: { description: 'Return an array with elements in reverse order', @@ -5191,7 +5207,7 @@ export const globalfunctions: IEntries = { }, call_user_method: { description: 'Call a user method on an specific object', - signature: '( string $method_name , object $obj [, mixed $parameter [, mixed $... ]]): mixed' + signature: '( string $method_name , object $obj [, mixed $... ]): mixed' }, class_alias: { description: 'Creates an alias for a class', @@ -5243,7 +5259,7 @@ export const globalfunctions: IEntries = { }, is_a: { description: 'Checks if the object is of this class or has this class as one of its parents', - signature: '( object $object , string $class_name [, bool $allow_string ]): bool' + signature: '( mixed $object , string $class_name [, bool $allow_string ]): bool' }, is_subclass_of: { description: 'Checks if the object has this class as one of its parents or implements it', @@ -5339,7 +5355,7 @@ export const globalfunctions: IEntries = { }, call_user_func: { description: 'Call the callback given by the first parameter', - signature: '( callable $callback [, mixed $parameter [, mixed $... ]]): mixed' + signature: '( callable $callback [, mixed $... ]): mixed' }, create_function: { description: 'Create an anonymous (lambda-style) function', @@ -5351,7 +5367,7 @@ export const globalfunctions: IEntries = { }, forward_static_call: { description: 'Call a static method', - signature: '( callable $function [, mixed $parameter [, mixed $... ]]): mixed' + signature: '( callable $function [, mixed $... ]): mixed' }, func_get_arg: { description: 'Return an item from the argument list', @@ -5375,15 +5391,15 @@ export const globalfunctions: IEntries = { }, register_shutdown_function: { description: 'Register a function for execution on shutdown', - signature: '( callable $callback [, mixed $parameter [, mixed $... ]]): void' + signature: '( callable $callback [, mixed $... ]): void' }, register_tick_function: { description: 'Register a function for execution on each tick', - signature: '( callable $function [, mixed $arg [, mixed $... ]]): bool' + signature: '( callable $function [, mixed $... ]): bool' }, unregister_tick_function: { description: 'De-register a function for execution on each tick', - signature: '( string $function_name ): void' + signature: '( callable $function ): void' }, boolval: { description: 'Get the boolean value of a variable', @@ -5436,6 +5452,10 @@ export const globalfunctions: IEntries = { description: 'Verify that the contents of a variable can be called as a function', signature: '( mixed $var [, bool $syntax_only [, string $callable_name ]]): bool' }, + is_countable: { + description: 'Verify that the contents of a variable is a countable value', + signature: '( mixed $var ): array' + }, is_double: { description: 'Alias of is_float', }, @@ -5485,7 +5505,7 @@ export const globalfunctions: IEntries = { signature: '( mixed $var ): bool' }, isset: { - description: 'Determine if a variable is set and is not NULL', + description: 'Determine if a variable is declared and is different than NULL', signature: '( mixed $var [, mixed $... ]): bool' }, print_r: { @@ -5590,7 +5610,7 @@ export const globalfunctions: IEntries = { }, com_load_typelib: { description: 'Loads a Typelib', - signature: '( string $typelib_name [, bool $case_insensitive ]): bool' + signature: '( string $typelib_name [, bool $case_sensitive ]): bool' }, com_message_pump: { description: 'Process COM messages, sleeping for up to timeoutms milliseconds', diff --git a/extensions/php-language-features/yarn.lock b/extensions/php-language-features/yarn.lock index 5e39a356be6..e6247e29255 100644 --- a/extensions/php-language-features/yarn.lock +++ b/extensions/php-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/php/.vscodeignore b/extensions/php/.vscodeignore index 98efc0327fb..5da0ed79e46 100644 --- a/extensions/php/.vscodeignore +++ b/extensions/php/.vscodeignore @@ -4,3 +4,4 @@ out/test/** src/** tsconfig.json cgmanifest.json +.vscode \ No newline at end of file diff --git a/extensions/php/build/update-grammar.js b/extensions/php/build/update-grammar.js index a6bf6d52721..58b1207a4a2 100644 --- a/extensions/php/build/update-grammar.js +++ b/extensions/php/build/update-grammar.js @@ -23,16 +23,40 @@ function adaptInjectionScope(grammar) { // Workaround for https://github.com/Microsoft/vscode/issues/40279 // and https://github.com/Microsoft/vscode-textmate/issues/59 function fixBadRegex(grammar) { + function fail(msg) { + throw new Error(`fixBadRegex callback couldn't patch ${msg}. It may be obsolete`); + } + const scopeResolution = grammar.repository['scope-resolution']; if (scopeResolution) { const match = scopeResolution.patterns[0].match; if (match === '(?i)([a-z_\\x{7f}-\\x{7fffffff}\\\\][a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]*)(?=\\s*::)') { scopeResolution.patterns[0].match = '([A-Za-z_\\x{7f}-\\x{7fffffff}\\\\][A-Za-z0-9_\\x{7f}-\\x{7fffffff}\\\\]*)(?=\\s*::)'; - return; + } else { + fail('scope-resolution.match'); } + } else { + fail('scope-resolution'); } - throw new Error(`fixBadRegex callback couldn't patch the regex. It may be obsolete`); + const functionCall = grammar.repository['function-call']; + if (functionCall) { + const begin0 = functionCall.patterns[0].begin; + if (begin0 === '(?xi)\n(\n \\\\?(?{1,5})}", + "name": "constant.character.escape.powershell" + }, + { + "match": "`u(?:\\{[0-9a-fA-F]{,6}.)?", + "name": "invalid.character.escape.powershell" + } + ] + }, "function": { "begin": "^(?:\\s*+)(?i)(function|filter|configuration|workflow)\\s+(?:(global|local|script|private):)?((?:\\p{L}|\\d|_|-|\\.)+)", "beginCaptures": { @@ -677,7 +645,7 @@ { "captures": { "0": { - "name": "support.constant.automatic.powershell" + "name": "support.variable.automatic.powershell" }, "1": { "name": "punctuation.definition.variable.powershell" @@ -687,7 +655,7 @@ } }, "comment": "Automatic variables are not constants, but they are read-only. In monokai (default) color schema support.variable doesn't have color, so we use constant.", - "match": "(\\$)(?i:(\\$|\\^|\\?|_|Args|ConsoleFileName|Event|EventArgs|EventSubscriber|ForEach|Input|LastExitCode|Matches|MyInvocation|NestedPromptLevel|Profile|PSBoundParameters|PsCmdlet|PsCulture|PSDebugContext|PSItem|PSCommandPath|PSScriptRoot|PsUICulture|Pwd|Sender|SourceArgs|SourceEventArgs|StackTrace|Switch|This))((?:\\.(?:\\p{L}|\\d|_)+)*\\b)?\\b" + "match": "(\\$)((?:[$^?])|(?i:_|Args|ConsoleFileName|Event|EventArgs|EventSubscriber|ForEach|Input|LastExitCode|Matches|MyInvocation|NestedPromptLevel|Profile|PSBoundParameters|PsCmdlet|PsCulture|PSDebugContext|PSItem|PSCommandPath|PSScriptRoot|PsUICulture|Pwd|Sender|SourceArgs|SourceEventArgs|StackTrace|Switch|This)\\b)((?:\\.(?:\\p{L}|\\d|_)+)*\\b)?" }, { "captures": { @@ -702,7 +670,7 @@ } }, "comment": "Style preference variables as language variables so that they stand out.", - "match": "(\\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|ProgressPreference|PsCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|VerbosePreference|WarningPreference|WhatIfPreference))((?:\\.(?:\\p{L}|\\d|_)+)*\\b)?\\b" + "match": "(\\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|InformationPreference|LogCommandHealthEvent|LogCommandLifecycleEvent|LogEngineHealthEvent|LogEngineLifecycleEvent|LogProviderHealthEvent|LogProviderLifecycleEvent|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|PSCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoLoadingPreference|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|ProgressPreference|VerbosePreference|WarningPreference|WhatIfPreference))((?:\\.(?:\\p{L}|\\d|_)+)*\\b)?\\b" }, { "captures": { @@ -865,7 +833,7 @@ } }, "comment": "Automatic variables are not constants, but they are read-only...", - "match": "(\\$)(?i:(\\$|\\^|\\?|_|Args|ConsoleFileName|Event|EventArgs|EventSubscriber|ForEach|Input|LastExitCode|Matches|MyInvocation|NestedPromptLevel|Profile|PSBoundParameters|PsCmdlet|PsCulture|PSDebugContext|PSItem|PSCommandPath|PSScriptRoot|PsUICulture|Pwd|Sender|SourceArgs|SourceEventArgs|StackTrace|Switch|This))\\b" + "match": "(\\$)((?:[$^?])|(?i:_|Args|ConsoleFileName|Event|EventArgs|EventSubscriber|ForEach|Input|LastExitCode|Matches|MyInvocation|NestedPromptLevel|Profile|PSBoundParameters|PsCmdlet|PsCulture|PSDebugContext|PSItem|PSCommandPath|PSScriptRoot|PsUICulture|Pwd|Sender|SourceArgs|SourceEventArgs|StackTrace|Switch|This)\\b)" }, { "captures": { @@ -880,7 +848,7 @@ } }, "comment": "Style preference variables as language variables so that they stand out.", - "match": "(\\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|ProgressPreference|PsCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|VerbosePreference|WarningPreference|WhatIfPreference))\\b" + "match": "(\\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|InformationPreference|LogCommandHealthEvent|LogCommandLifecycleEvent|LogEngineHealthEvent|LogEngineLifecycleEvent|LogProviderHealthEvent|LogProviderLifecycleEvent|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|PSCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoLoadingPreference|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|ProgressPreference|VerbosePreference|WarningPreference|WhatIfPreference))\\b" }, { "captures": { @@ -897,7 +865,7 @@ "name": "variable.other.member.powershell" } }, - "match": "(?i:(\\$|@)(global|local|private|script|using|workflow):((?:\\p{L}|\\d|_)+))" + "match": "(?i:(\\$)(global|local|private|script|using|workflow):((?:\\p{L}|\\d|_)+))" }, { "captures": { @@ -1023,9 +991,6 @@ { "include": "#variableNoProperty" }, - { - "include": "#variable" - }, { "include": "#doubleQuotedStringEscapes" }, diff --git a/extensions/powershell/test/colorize-results/test_ps1.json b/extensions/powershell/test/colorize-results/test_ps1.json index fd82cda536b..67380ce77b6 100644 --- a/extensions/powershell/test/colorize-results/test_ps1.json +++ b/extensions/powershell/test/colorize-results/test_ps1.json @@ -465,11 +465,11 @@ "c": ".IsInRole", "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell variable.other.readwrite.powershell variable.other.member.powershell", "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", + "dark_plus": "source.powershell variable.other.member: #DCDCAA", + "light_plus": "source.powershell variable.other.member: #795E26", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "variable: #9CDCFE" + "hc_black": "source.powershell variable.other.member: #DCDCAA" } }, { @@ -716,24 +716,24 @@ }, { "c": "$", - "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell support.constant.automatic.powershell punctuation.definition.variable.powershell", + "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell support.variable.automatic.powershell punctuation.definition.variable.powershell", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "support.variable: #9CDCFE", + "light_plus": "support.variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "support.variable: #9CDCFE" } }, { "c": "_", - "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell support.constant.automatic.powershell", + "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell support.variable.automatic.powershell", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "support.variable: #9CDCFE", + "light_plus": "support.variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "support.variable: #9CDCFE" } }, { @@ -1090,24 +1090,24 @@ }, { "c": "$", - "t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell punctuation.definition.variable.powershell", + "t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.variable.automatic.powershell punctuation.definition.variable.powershell", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "support.variable: #9CDCFE", + "light_plus": "support.variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "support.variable: #9CDCFE" } }, { "c": "_", - "t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell", + "t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.variable.automatic.powershell", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "support.variable: #9CDCFE", + "light_plus": "support.variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "support.variable: #9CDCFE" } }, { @@ -1299,24 +1299,24 @@ }, { "c": "$", - "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell punctuation.definition.variable.powershell", + "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.variable.automatic.powershell punctuation.definition.variable.powershell", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "support.variable: #9CDCFE", + "light_plus": "support.variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "support.variable: #9CDCFE" } }, { "c": "_", - "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell", + "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.variable.automatic.powershell", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "support.variable: #9CDCFE", + "light_plus": "support.variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "support.variable: #9CDCFE" } }, { @@ -1486,24 +1486,24 @@ }, { "c": "$", - "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell punctuation.definition.variable.powershell", + "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.variable.automatic.powershell punctuation.definition.variable.powershell", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "support.variable: #9CDCFE", + "light_plus": "support.variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "support.variable: #9CDCFE" } }, { "c": "matches", - "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell", + "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.variable.automatic.powershell", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "support.variable: #9CDCFE", + "light_plus": "support.variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "support.variable: #9CDCFE" } }, { @@ -1563,24 +1563,24 @@ }, { "c": "$", - "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell punctuation.definition.variable.powershell", + "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.variable.automatic.powershell punctuation.definition.variable.powershell", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "support.variable: #9CDCFE", + "light_plus": "support.variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "support.variable: #9CDCFE" } }, { "c": "matches", - "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell", + "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.variable.automatic.powershell", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "support.variable: #9CDCFE", + "light_plus": "support.variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "support.variable: #9CDCFE" } }, { diff --git a/extensions/pug/cgmanifest.json b/extensions/pug/cgmanifest.json index cdfc2ded989..e7bd7bccc09 100644 --- a/extensions/pug/cgmanifest.json +++ b/extensions/pug/cgmanifest.json @@ -15,4 +15,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/pug/package.json b/extensions/pug/package.json index 270cc4b5e7c..19049be77af 100644 --- a/extensions/pug/package.json +++ b/extensions/pug/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js davidrios/pug-tmbundle Syntaxes/Pug.JSON-tmLanguage ./syntaxes/pug.tmLanguage.json" diff --git a/extensions/pug/test/colorize-results/test_pug.json b/extensions/pug/test/colorize-results/test_pug.json index ef42ebe541b..a022fd80cd0 100644 --- a/extensions/pug/test/colorize-results/test_pug.json +++ b/extensions/pug/test/colorize-results/test_pug.json @@ -848,7 +848,7 @@ }, { "c": "user", - "t": "text.pug meta.control.flow.pug variable.other.readwrite.js", + "t": "text.pug meta.control.flow.pug js.embedded.control.flow.pug variable.other.readwrite.js", "r": { "dark_plus": "variable: #9CDCFE", "light_plus": "variable: #001080", @@ -1617,7 +1617,7 @@ } }, { - "c": " ", + "c": " samp", "t": "text.pug inline.pug", "r": { "dark_plus": "default: #D4D4D4", @@ -1627,17 +1627,6 @@ "hc_black": "default: #FFFFFF" } }, - { - "c": "samp", - "t": "text.pug inline.pug tag.inline.pug meta.tag.other entity.name.tag.pug", - "r": { - "dark_plus": "entity.name.tag: #569CD6", - "light_plus": "entity.name.tag: #800000", - "dark_vs": "entity.name.tag: #569CD6", - "light_vs": "entity.name.tag: #800000", - "hc_black": "entity.name.tag: #569CD6" - } - }, { "c": "]", "t": "text.pug inline.pug entity.name.function.pug", @@ -1683,7 +1672,7 @@ } }, { - "c": " ", + "c": " This is sample text", "t": "text.pug inline.pug", "r": { "dark_plus": "default: #D4D4D4", @@ -1693,83 +1682,6 @@ "hc_black": "default: #FFFFFF" } }, - { - "c": "This", - "t": "text.pug inline.pug tag.inline.pug meta.tag.other entity.name.tag.pug", - "r": { - "dark_plus": "entity.name.tag: #569CD6", - "light_plus": "entity.name.tag: #800000", - "dark_vs": "entity.name.tag: #569CD6", - "light_vs": "entity.name.tag: #800000", - "hc_black": "entity.name.tag: #569CD6" - } - }, - { - "c": " ", - "t": "text.pug inline.pug", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "is", - "t": "text.pug inline.pug tag.inline.pug meta.tag.other entity.name.tag.pug", - "r": { - "dark_plus": "entity.name.tag: #569CD6", - "light_plus": "entity.name.tag: #800000", - "dark_vs": "entity.name.tag: #569CD6", - "light_vs": "entity.name.tag: #800000", - "hc_black": "entity.name.tag: #569CD6" - } - }, - { - "c": " ", - "t": "text.pug inline.pug", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "sample", - "t": "text.pug inline.pug tag.inline.pug meta.tag.other entity.name.tag.pug", - "r": { - "dark_plus": "entity.name.tag: #569CD6", - "light_plus": "entity.name.tag: #800000", - "dark_vs": "entity.name.tag: #569CD6", - "light_vs": "entity.name.tag: #800000", - "hc_black": "entity.name.tag: #569CD6" - } - }, - { - "c": " ", - "t": "text.pug inline.pug", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "text", - "t": "text.pug inline.pug tag.inline.pug meta.tag.other entity.name.tag.pug", - "r": { - "dark_plus": "entity.name.tag: #569CD6", - "light_plus": "entity.name.tag: #800000", - "dark_vs": "entity.name.tag: #569CD6", - "light_vs": "entity.name.tag: #800000", - "hc_black": "entity.name.tag: #569CD6" - } - }, { "c": "]", "t": "text.pug inline.pug entity.name.function.pug", diff --git a/extensions/python/.vscodeignore b/extensions/python/.vscodeignore index 89fb2149dcb..4d5a14fc91e 100644 --- a/extensions/python/.vscodeignore +++ b/extensions/python/.vscodeignore @@ -1,4 +1,6 @@ test/** src/** tsconfig.json +extension.webpack.config.js cgmanifest.json +.vscode \ No newline at end of file diff --git a/extensions/python/cgmanifest.json b/extensions/python/cgmanifest.json index 66490a1ec9a..139ae46369b 100644 --- a/extensions/python/cgmanifest.json +++ b/extensions/python/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "MagicStack/MagicPython", "repositoryUrl": "https://github.com/MagicStack/MagicPython", - "commitHash": "8ff35b3e5fcde471fae62a57ea1ae1c7cd34c9fc" + "commitHash": "38422d302fe0b3e7716d26ce8cd7d0b9685f3a38" } }, "license": "MIT", diff --git a/extensions/python/extension.webpack.config.js b/extensions/python/extension.webpack.config.js new file mode 100644 index 00000000000..1467031c5a2 --- /dev/null +++ b/extensions/python/extension.webpack.config.js @@ -0,0 +1,17 @@ +/*--------------------------------------------------------------------------------------------- + * 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 withDefaults = require('../shared.webpack.config'); + +module.exports = withDefaults({ + context: __dirname, + entry: { + pythonMain: './src/pythonMain.ts' + } +}); diff --git a/extensions/python/package.json b/extensions/python/package.json index 48151bd6245..645cba2bae3 100644 --- a/extensions/python/package.json +++ b/extensions/python/package.json @@ -4,14 +4,16 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "activationEvents": ["onLanguage:python"], "main": "./out/pythonMain", "contributes": { "languages": [{ "id": "python", - "extensions": [ ".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi", ".snakefile", ".smk"], + "extensions": [ ".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi", ".pyi", ".ipy"], "aliases": [ "Python", "py" ], + "filenames": [ "Snakefile" ], "firstLine": "^#!\\s*/.*\\bpython[0-9.-]*\\b", "configuration": "./language-configuration.json" }], diff --git a/extensions/python/syntaxes/MagicPython.tmLanguage.json b/extensions/python/syntaxes/MagicPython.tmLanguage.json index e51fcce1a85..d89e7ed110d 100644 --- a/extensions/python/syntaxes/MagicPython.tmLanguage.json +++ b/extensions/python/syntaxes/MagicPython.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/MagicStack/MagicPython/commit/8ff35b3e5fcde471fae62a57ea1ae1c7cd34c9fc", + "version": "https://github.com/MagicStack/MagicPython/commit/38422d302fe0b3e7716d26ce8cd7d0b9685f3a38", "name": "MagicPython", "scopeName": "source.python", "patterns": [ @@ -827,7 +827,7 @@ ] }, "f-expression": { - "comment": "All valid Python expressions, except comments and line cont", + "comment": "All valid Python expressions, except comments and line continuation", "patterns": [ { "include": "#expression-bare" diff --git a/extensions/r/package.json b/extensions/r/package.json index c9b682918b4..63ff6a6dcbc 100644 --- a/extensions/r/package.json +++ b/extensions/r/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js Ikuyadeu/vscode-R syntax/r.json ./syntaxes/r.tmLanguage.json" diff --git a/extensions/razor/package.json b/extensions/razor/package.json index f4432ee986d..98147bed692 100644 --- a/extensions/razor/package.json +++ b/extensions/razor/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "0.10.x" }, @@ -25,7 +26,7 @@ "embeddedLanguages": { "section.embedded.source.cshtml": "csharp", "source.css": "css", - "source.js": "javascript" + "source.js": "javascript" } }] } diff --git a/extensions/ruby/cgmanifest.json b/extensions/ruby/cgmanifest.json index dd4b29e5184..8f04db20f54 100644 --- a/extensions/ruby/cgmanifest.json +++ b/extensions/ruby/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "textmate/ruby.tmbundle", "repositoryUrl": "https://github.com/textmate/ruby.tmbundle", - "commitHash": "74713556df10fbc7b1f9e99013ab1e34cd836f56" + "commitHash": "05698e99314d8653e2e9d8f198d3c83e387ee1eb" } }, "licenseDetail": [ @@ -29,4 +29,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/ruby/package.json b/extensions/ruby/package.json index 98d66a891e4..4572f2526d8 100644 --- a/extensions/ruby/package.json +++ b/extensions/ruby/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js textmate/ruby.tmbundle Syntaxes/Ruby.plist ./syntaxes/ruby.tmLanguage.json" @@ -11,7 +12,7 @@ "contributes": { "languages": [{ "id": "ruby", - "extensions": [ ".rb", ".rbx", ".rjs", ".gemspec", ".rake", ".ru", ".erb" ], + "extensions": [ ".rb", ".rbx", ".rjs", ".gemspec", ".rake", ".ru", ".erb", ".podspec", ".rbi" ], "filenames": [ "rakefile", "gemfile", "guardfile", "podfile", "capfile" ], "aliases": [ "Ruby", "rb" ], "firstLine": "^#!\\s*/.*\\bruby\\b", diff --git a/extensions/ruby/syntaxes/ruby.tmLanguage.json b/extensions/ruby/syntaxes/ruby.tmLanguage.json index 62fbbc265e5..8b6c98616d8 100644 --- a/extensions/ruby/syntaxes/ruby.tmLanguage.json +++ b/extensions/ruby/syntaxes/ruby.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/textmate/ruby.tmbundle/commit/74713556df10fbc7b1f9e99013ab1e34cd836f56", + "version": "https://github.com/textmate/ruby.tmbundle/commit/05698e99314d8653e2e9d8f198d3c83e387ee1eb", "name": "Ruby", "scopeName": "source.ruby", "comment": "\n\tTODO: unresolved issues\n\n\ttext:\n\t\"p <<<[-~](\"?)((?:[_\\w]+_|)HTML)\\b\\1))", "comment": "Heredoc with embedded html", diff --git a/extensions/rust/cgmanifest.json b/extensions/rust/cgmanifest.json index c3056722ece..5181efba1c4 100644 --- a/extensions/rust/cgmanifest.json +++ b/extensions/rust/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "language-rust", "repositoryUrl": "https://github.com/zargony/atom-language-rust", - "commitHash": "5238d9834953ed7c58d9b5b9bb0c084c3c11ecd6" + "commitHash": "7d59e2ad79fbe5925bd2fd3bd3857bf9f421ff6f" } }, "license": "MIT", diff --git a/extensions/rust/package.json b/extensions/rust/package.json index 4436da8bcaf..66078388175 100644 --- a/extensions/rust/package.json +++ b/extensions/rust/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js zargony/atom-language-rust grammars/rust.cson ./syntaxes/rust.tmLanguage.json" diff --git a/extensions/rust/syntaxes/rust.tmLanguage.json b/extensions/rust/syntaxes/rust.tmLanguage.json index 9b7373336df..784bd8c9aca 100644 --- a/extensions/rust/syntaxes/rust.tmLanguage.json +++ b/extensions/rust/syntaxes/rust.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/zargony/atom-language-rust/commit/5238d9834953ed7c58d9b5b9bb0c084c3c11ecd6", + "version": "https://github.com/zargony/atom-language-rust/commit/7d59e2ad79fbe5925bd2fd3bd3857bf9f421ff6f", "name": "Rust", "scopeName": "source.rust", "patterns": [ @@ -160,7 +160,7 @@ { "comment": "Control keyword", "name": "keyword.control.rust", - "match": "\\b(break|continue|else|if|in|for|loop|match|return|while)\\b" + "match": "\\b(async|await|break|continue|else|if|in|for|loop|match|return|try|while)\\b" }, { "comment": "Keyword", diff --git a/extensions/scss/cgmanifest.json b/extensions/scss/cgmanifest.json index 0d3b37497f1..a67a4f54609 100644 --- a/extensions/scss/cgmanifest.json +++ b/extensions/scss/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "atom/language-sass", "repositoryUrl": "https://github.com/atom/language-sass", - "commitHash": "804a935ea1d50504e14a7f602e2bb133fee8450c" + "commitHash": "303bbf0c250fe380b9e57375598cfd916110758b" } }, "license": "MIT", diff --git a/extensions/scss/package.json b/extensions/scss/package.json index 060bda69899..39338e30e2e 100644 --- a/extensions/scss/package.json +++ b/extensions/scss/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js atom/language-sass grammars/scss.cson ./syntaxes/scss.tmLanguage.json grammars/sassdoc.cson ./syntaxes/sassdoc.tmLanguage.json" diff --git a/extensions/shaderlab/cgmanifest.json b/extensions/shaderlab/cgmanifest.json index 3558286bc04..2dd540dc872 100644 --- a/extensions/shaderlab/cgmanifest.json +++ b/extensions/shaderlab/cgmanifest.json @@ -14,4 +14,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/shaderlab/package.json b/extensions/shaderlab/package.json index e20d103f954..d5f1f462f2c 100644 --- a/extensions/shaderlab/package.json +++ b/extensions/shaderlab/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, diff --git a/extensions/shared.tsconfig.json b/extensions/shared.tsconfig.json index 1cbda1bf9f0..bb42dd479cf 100644 --- a/extensions/shared.tsconfig.json +++ b/extensions/shared.tsconfig.json @@ -1,11 +1,7 @@ { "compilerOptions": { - "target": "es2017", + "target": "es2018", "module": "commonjs", - "lib": [ - "es6", - "es2015.promise" - ], "strict": true, "alwaysStrict": true, "noImplicitAny": true, diff --git a/extensions/shared.webpack.config.js b/extensions/shared.webpack.config.js index 2916167b057..2fba65c92bd 100644 --- a/extensions/shared.webpack.config.js +++ b/extensions/shared.webpack.config.js @@ -9,11 +9,17 @@ 'use strict'; const path = require('path'); +const fs = require('fs'); const merge = require('merge-options'); const CopyWebpackPlugin = require('copy-webpack-plugin'); - +const { NLSBundlePlugin } = require('vscode-nls-dev/lib/webpack-bundler'); module.exports = function withDefaults(/**@type WebpackConfig*/extConfig) { + // Need to find the top-most `package.json` file + const folderName = path.relative(__dirname, extConfig.context).split(/[\\\/]/)[0]; + const pkgPath = path.join(__dirname, folderName, 'package.json'); + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); + const id = `${pkg.publisher}.${pkg.name}`; /** @type WebpackConfig */ let defaultConfig = { @@ -51,8 +57,6 @@ module.exports = function withDefaults(/**@type WebpackConfig*/extConfig) { }, externals: { 'vscode': 'commonjs vscode', // ignored because it doesn't exist - - // "vscode-extension-telemetry": 'commonjs vscode-extension-telemetry', // commonly used }, output: { // all output goes into `dist`. @@ -64,9 +68,11 @@ module.exports = function withDefaults(/**@type WebpackConfig*/extConfig) { // yes, really source maps devtool: 'source-map', plugins: [ + // @ts-ignore new CopyWebpackPlugin([ - { from: './out/**/*', to: '.', ignore: ['*.js', '*.js.map'], flatten: true } - ]) + { from: 'src', to: '.', ignore: ['**/test/**', '*.ts'] } + ]), + new NLSBundlePlugin(id) ], }; diff --git a/extensions/shellscript/language-configuration.json b/extensions/shellscript/language-configuration.json index 01b6a8a2823..964623ac4cc 100644 --- a/extensions/shellscript/language-configuration.json +++ b/extensions/shellscript/language-configuration.json @@ -22,5 +22,11 @@ ["\"", "\""], ["'", "'"], ["`", "`"] - ] -} \ No newline at end of file + ], + "folding": { + "markers": { + "start": "^\\s*#\\s*#?region\\b.*", + "end": "^\\s*#\\s*#?endregion\\b.*" + } + } +} diff --git a/extensions/shellscript/package.json b/extensions/shellscript/package.json index b3c2346380d..a55af2b08ff 100644 --- a/extensions/shellscript/package.json +++ b/extensions/shellscript/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js atom/language-shellscript grammars/shell-unix-bash.cson ./syntaxes/shell-unix-bash.tmLanguage.json" @@ -13,8 +14,8 @@ "id": "shellscript", "aliases": ["Shell Script", "shellscript", "bash", "sh", "zsh", "ksh"], "extensions": [".sh", ".bash", ".bashrc", ".bash_aliases", ".bash_profile", ".bash_login", ".ebuild", ".install", ".profile", ".bash_logout", ".zsh", ".zshrc", ".zprofile", ".zlogin", ".zlogout", ".zshenv", ".zsh-theme", ".ksh"], - "filenames": ["PKGBUILD"], - "firstLine": "^#!.*\\b(bash|zsh|sh|tcsh|ksh).*|^#\\s*-\\*-[^*]*mode:\\s*shell-script[^*]*-\\*-", + "filenames": ["APKBUILD", "PKGBUILD"], + "firstLine": "^#!.*\\b(bash|zsh|sh|tcsh|ksh|ash|qsh).*|^#\\s*-\\*-[^*]*mode:\\s*shell-script[^*]*-\\*-", "configuration": "./language-configuration.json", "mimetypes": ["text/x-shellscript"] }], diff --git a/extensions/sql/cgmanifest.json b/extensions/sql/cgmanifest.json index db3a5db2b06..7abcea36e5d 100644 --- a/extensions/sql/cgmanifest.json +++ b/extensions/sql/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "Microsoft/vscode-mssql", "repositoryUrl": "https://github.com/Microsoft/vscode-mssql", - "commitHash": "3aa44d04b04d219ad5fa8f411ca9dd32294a7a06" + "commitHash": "a79741f76fd33bd137a8c28172c9750b978309b6" } }, "license": "MIT", - "version": "1.4.0" + "version": "1.6.0" } ], "version": 1 diff --git a/extensions/sql/package.json b/extensions/sql/package.json index f0256026d4c..8c283e97246 100644 --- a/extensions/sql/package.json +++ b/extensions/sql/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-mssql syntaxes/SQL.plist ./syntaxes/sql.tmLanguage.json" diff --git a/extensions/sql/syntaxes/sql.tmLanguage.json b/extensions/sql/syntaxes/sql.tmLanguage.json index 516b7ef6154..1dd6903783f 100644 --- a/extensions/sql/syntaxes/sql.tmLanguage.json +++ b/extensions/sql/syntaxes/sql.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/vscode-mssql/commit/3aa44d04b04d219ad5fa8f411ca9dd32294a7a06", + "version": "https://github.com/Microsoft/vscode-mssql/commit/a79741f76fd33bd137a8c28172c9750b978309b6", "name": "SQL", "scopeName": "source.sql", "patterns": [ @@ -17,7 +17,7 @@ "name": "text.bracketed" }, { - "match": "\\b(?i)(abort|abort_after_wait|absent|absolute|accent_sensitivity|acceptable_cursopt|acp|action|activation|address|admin|aes_128|aes_192|aes_256|affinity|after|aggregate|algorithm|all_constraints|all_errormsgs|all_indexes|all_levels|all_results|allow_connections|allow_dup_row|allow_encrypted_value_modifications|allow_page_locks|allow_row_locks|allow_snapshot_isolation|altercolumn|always|anonymous|ansi_defaults|ansi_null_default|ansi_null_dflt_off|ansi_null_dflt_on|ansi_nulls|ansi_padding|ansi_warnings|appdomain|append|application|apply|arithabort|arithignore|assembly|asymmetric|asynchronous_commit|at|atan2|atomic|attach|attach_force_rebuild_log|attach_rebuild_log|audit|auth_realm|authentication|auto|auto_cleanup|auto_close|auto_create_statistics|auto_shrink|auto_update_statistics|auto_update_statistics_async|automated_backup_preference |automatic|autopilot|availability|availability_mode|backup_priority|base64|basic|batches|batchsize|before|bigint|binary|binding|bit|block|blocksize|bmk|break|broker|broker_instance|bucket_count|buffer|buffercount|bulk_logged|by|call|caller|card|case|cast|catalog|catch|cert|certificate|change_retention|change_tracking|change_tracking_context|changes|char|character|character_set|check_expiration|check_policy|checkconstraints|checkindex|checkpoint|cleanup_policy|clear|clear_port|close|codepage|collection|column_encryption_key|column_master_key|columnstore|columnstore_archive|colv_80_to_100|colv_100_to_80|commit_differential_base|committed|compatibility_level|compress_all_row_groups|compression|compression_delay|concat_null_yields_null|concatenate|configuration|connect|continue|continue_after_error|contract|contract_name|control|conversation|conversation_group_id|conversation_handle|copy|copy_only|count_rows|counter|create(\\s+or\\s+alter)?|credential|cross|cryptographic|cryptographic_provider|cube|cursor_close_on_commit|cursor_default|data|data_compression|data_flush_interval_seconds|data_mirroring|data_purity|data_source|database|database_name|database_snapshot|datafiletype|date_correlation_optimization|date|datefirst|dateformat|date_format|datetime|datetime2|datetimeoffset|days|db_chaining|dbid|dbidexec|dbo_only|deadlock_priority|deallocate|dec|decimal|declare(\\s+cursor)?|decrypt|decrypt_a|decryption|default_database|default_language|default_logon_domain|default_schema|definition|delay|delayed_durability|delimitedtext|density_vector|dependent|des|description|desired_state|desx|differential|digest|disable|disable_broker|disable_def_cnst_chk|disabled|disk|distributed|distribution|drop|drop_existing|dts_buffers|dump|durability|dynamic|edition|elements|else|emergency|empty|enable|enable_broker|enabled|encoding|encrypted|encrypted_value|encryption|encryption_type|end|endpoint|endpoint_url|enhancedintegrity|entry|error_broker_conversations|errorfile|estimateonly|event|exec|executable|execute|exists|expand|expiredate|expiry_date|explicit|external_access|failover|failover_mode|failure_condition_level|fast|fast_forward|fastfirstrow|federated_service_account|fetch|field_terminator|fieldterminator|file|filelistonly|filegroup|filename|filestream|filestream_log|filestream_on|filetable|file_format|filter|fips_flagger|fire_triggers|first|firstrow|float|flush_interval_seconds|fmtonly|following|force|force_failover_allow_data_loss|force_service_allow_data_loss|forced|forceplan|formatfile|format_options|format_type|formsof|forward_only|free_cursors|free_exec_context|fullscan|fulltext|fulltextall|fulltextkey|function|generated|get|geography|geometry|global|go|goto|governor|guid|hadoop|hardening|hash|hashed|header_limit|headeronly|health_check_timeout|hidden|hierarchyid|histogram|histogram_steps|hits_cursors|hits_exec_context|hours|http|identity|identity_value|if|ifnull|ignore_constraints|ignore_dup_key|ignore_dup_row|ignore_triggers|image|immediate|implicit_transactions|include|include_null_values|inflectional|init|initiator|insensitive|insert|instead|int|integer|integrated|intermediate|interval_length_minutes|into|inuse_cursors|inuse_exec_context|io|is|isabout|iso_week|isolation|job_tracker_location|json|keep|keep_nulls|keep_replication|keepdefaults|keepfixed|keepidentity|keepnulls|kerberos|key|key_path|key_source|key_store_provider_name|keyset|kill|kilobytes_per_batch|labelonly|langid|language|last|lastrow|legacy_cardinality_estimation|length|level|lifetime|lineage_80_to_100|lineage_100_to_80|listener_ip|listener_port|load|loadhistory|lob_compaction|local|local_service_name|locate|location|lock_escalation|lock_timeout|lockres|login|login_type|loop|manual|mark_in_use_for_removal|masked|master|max_queue_readers|max_duration|max_outstanding_io_per_volume|maxdop|maxerrors|maxlength|maxtransfersize|max_plans_per_query|max_storage_size_mb|mediadescription|medianame|mediapassword|memogroup|memory_optimized|merge|message|message_forward_size|message_forwarding|microsecond|millisecond|minutes|mirror_address|misses_cursors|misses_exec_context|mixed|modify|money|move|multi_user|must_change|name|namespace|nanosecond|native|native_compilation|nchar|ncharacter|never|new_account|new_broker|newname|next|no|no_browsetable|no_checksum|no_compression|no_infomsgs|no_triggers|no_truncate|nocount|noexec|noexpand|noformat|noinit|nolock|nonatomic|nondurable|none|norecompute|norecovery|noreset|norewind|noskip|not|notification|nounload|now|nowait|ntext|ntlm|numeric|numeric_roundabort|nvarchar|object|objid|oem|offline|old_account|online|operation_mode|open|openjson|optimistic|option|orc|out|outer|output|over|override|owner|ownership|pad_index|page|page_checksum|page_verify|pagecount|paglock|param|parameter_sniffing|parameter_type_expansion|parameterization|parquet|parseonly|partial|partition|partner|password|path|pause|percentage|permission_set|persisted|period|physical_only|plan_forcing_mode|policy|pool|population|ports|preceding|precision|predicate|presume_abort|primary|primary_role|print|prior|priority |priority_level|private|proc(edure)?|procedure_name|profile|provider|query_capture_mode|query_governor_cost_limit|query_optimizer_hotfixes|query_store|queue|quoted_identifier|raiserror|range|raw|rcfile|rc2|rc4|rc4_128|rdbms|read_committed_snapshot|read|read_only|read_write|readcommitted|readcommittedlock|readonly|readpast|readuncommitted|readwrite|real|rebuild|receive|recmodel_70backcomp|recompile|reconfigure|recovery|recursive|recursive_triggers|redo_queue|reject_sample_value|reject_type|reject_value|relative|remote|remote_data_archive|remote_proc_transactions|remote_service_name|remove|removed_cursors|removed_exec_context|reorganize|repeat|repeatable|repeatableread|replica|replicated|replnick_100_to_80|replnickarray_80_to_100|replnickarray_100_to_80|required|required_cursopt|resample|reset|resource|resource_manager_location|restart|restore|restricted_user|resume|retaindays|retention|return|rewind|rewindonly|returns|robust|role|rollup|root|round_robin|route|row|rowdump|rowguidcol|rowlock|row_terminator|rows|rows_per_batch|rowsets_only|rowterminator|rowversion|rsa_1024|rsa_2048|rsa_3072|rsa_4096|rsa_512|safe|safety|sample|save|schemabinding|scoped|scroll|scroll_locks|sddl|secexpr|secondary|secondary_only|secondary_role|secret|security|securityaudit|selective|self|send|sent|sequence|serde_method|serializable|server|service|service_broker|service_name|service_objective|session_timeout|session|sessions|seterror|setopts|sets|shard_map_manager|shard_map_name|sharded|shared_memory|show_statistics|showplan_all|showplan_text|showplan_xml|showplan_xml_with_recompile|shrinkdb|shutdown|sid|signature|simple|single_blob|single_clob|single_nclob|single_user|singleton|site|size_based_cleanup_mode|skip|smalldatetime|smallint|smallmoney|snapshot|snapshot_import|snapshotrestorephase|soap|softnuma|sort_in_tempdb|sorted_data|sorted_data_reorg|spatial|sql|sql_bigint|sql_binary|sql_bit|sql_char|sql_date|sql_decimal|sql_double|sql_float|sql_guid|sql_handle|sql_longvarbinary|sql_longvarchar|sql_numeric|sql_real|sql_smallint|sql_time|sql_timestamp|sql_tinyint|sql_tsi_day|sql_tsi_frac_second|sql_tsi_hour|sql_tsi_minute|sql_tsi_month|sql_tsi_quarter|sql_tsi_second|sql_tsi_week|sql_tsi_year|sql_type_date|sql_type_time|sql_type_timestamp|sql_varbinary|sql_varchar|sql_variant|sql_wchar|sql_wlongvarchar|ssl|ssl_port|standard|standby|start|start_date|started|stat_header|state|statement|static|statistics|statistics_incremental|statistics_norecompute|statistics_only|statman|stats_stream|status|stop|stop_on_error|stopat|stopatmark|stopbeforemark|stoplist|stopped|string_delimiter|subject|supplemental_logging|supported|suspend|symmetric|synchronous_commit|synonym|sysname|system|system_time|system_versioning|table|tableresults|tablock|tablockx|take|tape|target|target_index|target_partition|tcp|temporal_history_retention|text|textimage_on|then|thesaurus|throw|time|timeout|timestamp|tinyint|to|top|torn_page_detection|track_columns_updated|tran|transaction|transfer|triple_des|triple_des_3key|truncate|trustworthy|try|tsql|type|type_desc|type_warning|tzoffset|uid|unbounded|uncommitted|uniqueidentifier|unlimited|unload|unlock|unsafe|updlock|url|use|useplan|useroptions|use_type_default|using|utcdatetime|valid_xml|validation|value|values|varbinary|varchar|verbose|verifyonly|version|view_metadata|virtual_device|visiblity|waitfor|webmethod|weekday|weight|well_formed_xml|when|while|widechar|widechar_ansi|widenative|windows|with|within|witness|without|without_array_wrapper|workload|wsdl|xact_abort|xlock|xml|xmlschema|xquery|xsinil|zone)\\b", + "match": "\\b(?i)(abort|abort_after_wait|absent|absolute|accent_sensitivity|acceptable_cursopt|acp|action|activation|address|admin|aes_128|aes_192|aes_256|affinity|after|aggregate|algorithm|all_constraints|all_errormsgs|all_indexes|all_levels|all_results|allow_connections|allow_dup_row|allow_encrypted_value_modifications|allow_page_locks|allow_row_locks|allow_snapshot_isolation|alter|altercolumn|always|anonymous|ansi_defaults|ansi_null_default|ansi_null_dflt_off|ansi_null_dflt_on|ansi_nulls|ansi_padding|ansi_warnings|appdomain|append|application|apply|arithabort|arithignore|assembly|asymmetric|asynchronous_commit|at|atan2|atomic|attach|attach_force_rebuild_log|attach_rebuild_log|audit|auth_realm|authentication|auto|auto_cleanup|auto_close|auto_create_statistics|auto_shrink|auto_update_statistics|auto_update_statistics_async|automated_backup_preference|automatic|autopilot|availability|availability_mode|backup_priority|base64|basic|batches|batchsize|before|between|bigint|binary|binding|bit|block|blocksize|bmk|break|broker|broker_instance|bucket_count|buffer|buffercount|bulk_logged|by|call|caller|card|case|cast|catalog|catch|cert|certificate|change_retention|change_tracking|change_tracking_context|changes|char|character|character_set|check_expiration|check_policy|checkconstraints|checkindex|checkpoint|cleanup_policy|clear|clear_port|close|codepage|collection|column_encryption_key|column_master_key|columnstore|columnstore_archive|colv_80_to_100|colv_100_to_80|commit_differential_base|committed|compatibility_level|compress_all_row_groups|compression|compression_delay|concat_null_yields_null|concatenate|configuration|connect|continue|continue_after_error|contract|contract_name|control|conversation|conversation_group_id|conversation_handle|copy|copy_only|count_rows|counter|create(\\s+or\\s+alter)?|credential|cross|cryptographic|cryptographic_provider|cube|cursor_close_on_commit|cursor_default|data|data_compression|data_flush_interval_seconds|data_mirroring|data_purity|data_source|database|database_name|database_snapshot|datafiletype|date_correlation_optimization|date|datefirst|dateformat|date_format|datetime|datetime2|datetimeoffset|days|db_chaining|dbid|dbidexec|dbo_only|deadlock_priority|deallocate|dec|decimal|declare(\\s+cursor)?|decrypt|decrypt_a|decryption|default_database|default_language|default_logon_domain|default_schema|definition|delay|delayed_durability|delimitedtext|density_vector|dependent|des|description|desired_state|desx|differential|digest|disable|disable_broker|disable_def_cnst_chk|disabled|disk|distinct|distributed|distribution|drop|drop_existing|dts_buffers|dump|durability|dynamic|edition|elements|else|emergency|empty|enable|enable_broker|enabled|encoding|encrypted|encrypted_value|encryption|encryption_type|end|endpoint|endpoint_url|enhancedintegrity|entry|error_broker_conversations|errorfile|estimateonly|event|except|exec|executable|execute|exists|expand|expiredate|expiry_date|explicit|external|external_access|failover|failover_mode|failure_condition_level|fast|fast_forward|fastfirstrow|federated_service_account|fetch|field_terminator|fieldterminator|file|filelistonly|filegroup|filename|filestream|filestream_log|filestream_on|filetable|file_format|filter|first_row|fips_flagger|fire_triggers|first|firstrow|float|flush_interval_seconds|fmtonly|following|force|force_failover_allow_data_loss|force_service_allow_data_loss|forced|forceplan|formatfile|format_options|format_type|formsof|forward_only|free_cursors|free_exec_context|fullscan|fulltext|fulltextall|fulltextkey|function|generated|get|geography|geometry|global|go|goto|governor|guid|hadoop|hardening|hash|hashed|header_limit|headeronly|health_check_timeout|hidden|hierarchyid|histogram|histogram_steps|hits_cursors|hits_exec_context|hours|http|identity|identity_value|if|ifnull|ignore_constraints|ignore_dup_key|ignore_dup_row|ignore_triggers|image|immediate|implicit_transactions|include|include_null_values|inflectional|init|initiator|insensitive|insert|instead|int|integer|integrated|intersect|intermediate|interval_length_minutes|into|inuse_cursors|inuse_exec_context|io|is|isabout|iso_week|isolation|job_tracker_location|json|keep|keep_nulls|keep_replication|keepdefaults|keepfixed|keepidentity|keepnulls|kerberos|key|key_path|key_source|key_store_provider_name|keyset|kill|kilobytes_per_batch|labelonly|langid|language|last|lastrow|legacy_cardinality_estimation|length|level|lifetime|lineage_80_to_100|lineage_100_to_80|listener_ip|listener_port|load|loadhistory|lob_compaction|local|local_service_name|locate|location|lock_escalation|lock_timeout|lockres|login|login_type|loop|manual|mark_in_use_for_removal|masked|master|max_queue_readers|max_duration|max_outstanding_io_per_volume|maxdop|maxerrors|maxlength|maxtransfersize|max_plans_per_query|max_storage_size_mb|mediadescription|medianame|mediapassword|memogroup|memory_optimized|merge|message|message_forward_size|message_forwarding|microsecond|millisecond|minutes|mirror_address|misses_cursors|misses_exec_context|mixed|modify|money|move|multi_user|must_change|name|namespace|nanosecond|native|native_compilation|nchar|ncharacter|never|new_account|new_broker|newname|next|no|no_browsetable|no_checksum|no_compression|no_infomsgs|no_triggers|no_truncate|nocount|noexec|noexpand|noformat|noinit|nolock|nonatomic|nondurable|none|norecompute|norecovery|noreset|norewind|noskip|not|notification|nounload|now|nowait|ntext|ntlm|numeric|numeric_roundabort|nvarchar|object|objid|oem|offline|old_account|online|operation_mode|open|openjson|optimistic|option|orc|out|outer|output|over|override|owner|ownership|pad_index|page|page_checksum|page_verify|pagecount|paglock|param|parameter_sniffing|parameter_type_expansion|parameterization|parquet|parseonly|partial|partition|partner|password|path|pause|percentage|permission_set|persisted|period|physical_only|plan_forcing_mode|policy|pool|population|ports|preceding|precision|predicate|presume_abort|primary|primary_role|print|prior|priority |priority_level|private|proc(edure)?|procedure_name|profile|provider|query_capture_mode|query_governor_cost_limit|query_optimizer_hotfixes|query_store|queue|quoted_identifier|raiserror|range|raw|rcfile|rc2|rc4|rc4_128|rdbms|read_committed_snapshot|read|read_only|read_write|readcommitted|readcommittedlock|readonly|readpast|readuncommitted|readwrite|real|rebuild|receive|recmodel_70backcomp|recompile|reconfigure|recovery|recursive|recursive_triggers|redo_queue|reject_sample_value|reject_type|reject_value|relative|remote|remote_data_archive|remote_proc_transactions|remote_service_name|remove|removed_cursors|removed_exec_context|reorganize|repeat|repeatable|repeatableread|replica|replicated|replnick_100_to_80|replnickarray_80_to_100|replnickarray_100_to_80|required|required_cursopt|resample|reset|resource|resource_manager_location|restart|restore|restricted_user|resume|retaindays|retention|return|revert|rewind|rewindonly|returns|robust|role|rollup|root|round_robin|route|row|rowdump|rowguidcol|rowlock|row_terminator|rows|rows_per_batch|rowsets_only|rowterminator|rowversion|rsa_1024|rsa_2048|rsa_3072|rsa_4096|rsa_512|safe|safety|sample|save|schema|schemabinding|scoped|scroll|scroll_locks|sddl|secexpr|secondary|secondary_only|secondary_role|secret|security|securityaudit|selective|self|send|sent|sequence|serde_method|serializable|server|service|service_broker|service_name|service_objective|session_timeout|session|sessions|seterror|setopts|sets|shard_map_manager|shard_map_name|sharded|shared_memory|show_statistics|showplan_all|showplan_text|showplan_xml|showplan_xml_with_recompile|shrinkdb|shutdown|sid|signature|simple|single_blob|single_clob|single_nclob|single_user|singleton|site|size_based_cleanup_mode|skip|smalldatetime|smallint|smallmoney|snapshot|snapshot_import|snapshotrestorephase|soap|softnuma|sort_in_tempdb|sorted_data|sorted_data_reorg|spatial|sql|sql_bigint|sql_binary|sql_bit|sql_char|sql_date|sql_decimal|sql_double|sql_float|sql_guid|sql_handle|sql_longvarbinary|sql_longvarchar|sql_numeric|sql_real|sql_smallint|sql_time|sql_timestamp|sql_tinyint|sql_tsi_day|sql_tsi_frac_second|sql_tsi_hour|sql_tsi_minute|sql_tsi_month|sql_tsi_quarter|sql_tsi_second|sql_tsi_week|sql_tsi_year|sql_type_date|sql_type_time|sql_type_timestamp|sql_varbinary|sql_varchar|sql_variant|sql_wchar|sql_wlongvarchar|ssl|ssl_port|standard|standby|start|start_date|started|stat_header|state|statement|static|statistics|statistics_incremental|statistics_norecompute|statistics_only|statman|stats_stream|status|stop|stop_on_error|stopat|stopatmark|stopbeforemark|stoplist|stopped|string_delimiter|subject|supplemental_logging|supported|suspend|symmetric|synchronous_commit|synonym|sysname|system|system_time|system_versioning|table|tableresults|tablock|tablockx|take|tape|target|target_index|target_partition|tcp|temporal_history_retention|text|textimage_on|then|thesaurus|throw|time|timeout|timestamp|tinyint|to|top|torn_page_detection|track_columns_updated|tran|transaction|transfer|triple_des|triple_des_3key|truncate|trustworthy|try|tsql|type|type_desc|type_warning|tzoffset|uid|unbounded|uncommitted|uniqueidentifier|unlimited|unload|unlock|unsafe|updlock|url|use|useplan|useroptions|use_type_default|using|utcdatetime|valid_xml|validation|value|values|varbinary|varchar|verbose|verifyonly|version|view_metadata|virtual_device|visiblity|waitfor|webmethod|weekday|weight|well_formed_xml|when|while|widechar|widechar_ansi|widenative|windows|with|within|witness|without|without_array_wrapper|workload|wsdl|xact_abort|xlock|xml|xmlschema|xquery|xsinil|zone)\\b", "name": "keyword.other.sql" }, { diff --git a/extensions/swift/package.json b/extensions/swift/package.json index e4e5380d9c7..f88ac07ea5e 100644 --- a/extensions/swift/package.json +++ b/extensions/swift/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js textmate/swift.tmbundle Syntaxes/Swift.tmLanguage ./syntaxes/swift.tmLanguage.json" diff --git a/extensions/swift/syntaxes/swift.tmLanguage.json b/extensions/swift/syntaxes/swift.tmLanguage.json index 490388e079a..2e2148073db 100644 --- a/extensions/swift/syntaxes/swift.tmLanguage.json +++ b/extensions/swift/syntaxes/swift.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/textmate/swift.tmbundle/commit/cec27af6662e3799120b208e64483efdfe5521f5", + "version": "https://github.com/textmate/swift.tmbundle/commit/bdc8ae07562060a566b33da3f62601bb5aababd1", "name": "Swift", "scopeName": "source.swift", "comment": "See swift.tmbundle/grammar-test.swift for test cases.", @@ -46,7 +46,7 @@ "name": "constant.numeric.swift" } }, - "match": "\\b((?:iOS|macOS|OSX|watchOS|tvOS)(?:ApplicationExtension)?)\\b(?:\\s+([0-9]+(?:\\.[0-9]+)*\\b))?" + "match": "\\b(swift|(?:iOS|macOS|OSX|watchOS|tvOS|UIKitForMac)(?:ApplicationExtension)?)\\b(?:\\s+([0-9]+(?:\\.[0-9]+)*\\b))?" }, { "begin": "\\b(introduced|deprecated|obsoleted)\\s*(:)\\s*", @@ -587,7 +587,24 @@ "match": "\\b(os)\\s*(\\()\\s*(?:(macOS|OSX|iOS|tvOS|watchOS|Android|Linux|FreeBSD|Windows|PS4)|\\w+)\\s*(\\))" }, { - "begin": "\\b(swift)\\s*(\\()", + "captures": { + "1": { + "name": "keyword.other.condition.swift" + }, + "2": { + "name": "punctuation.definition.parameters.begin.swift" + }, + "3": { + "name": "entity.name.type.module.swift" + }, + "4": { + "name": "punctuation.definition.parameters.end.swift" + } + }, + "match": "\\b(canImport)\\s*(\\()([\\p{L}_][\\p{L}_\\p{N}\\p{M}]*)(\\))" + }, + { + "begin": "\\b(targetEnvironment)\\s*(\\()", "beginCaptures": { "1": { "name": "keyword.other.condition.swift" @@ -604,7 +621,30 @@ }, "patterns": [ { - "match": ">=", + "match": "\\b(simulator|UIKitForMac)\\b", + "name": "support.constant.platform.environment.swift" + } + ] + }, + { + "begin": "\\b(swift|compiler)\\s*(\\()", + "beginCaptures": { + "1": { + "name": "keyword.other.condition.swift" + }, + "2": { + "name": "punctuation.definition.parameters.begin.swift" + } + }, + "end": "(\\))|$", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.swift" + } + }, + "patterns": [ + { + "match": ">=|<", "name": "keyword.operator.comparison.swift" }, { @@ -1977,22 +2017,27 @@ "include": "#comments" }, { - "captures": { + "begin": "(?x)\n\t\t\t\t\t\t\t\t\t\t(?:(_)|((?`?)[\\p{L}_][\\p{L}_\\p{N}\\p{M}]*\\k))\n\t\t\t\t\t\t\t\t\t\t\\s+\n\t\t\t\t\t\t\t\t\t\t(((?`?)[\\p{L}_][\\p{L}_\\p{N}\\p{M}]*\\k))\n\t\t\t\t\t\t\t\t\t\t\\s*(:)", + "beginCaptures": { "1": { - "name": "invalid.illegal.distinct-labels-not-allowed.swift" - }, - "3": { "name": "entity.name.function.swift" }, - "4": { + "2": { + "name": "invalid.illegal.distinct-labels-not-allowed.swift" + }, + "5": { "name": "variable.parameter.function.swift" }, - "6": { + "7": { "name": "punctuation.separator.argument-label.swift" } }, "end": "(?=[,)\\]])", - "match": "(?x)\n\t\t\t\t\t\t\t\t\t\t((?`?)[\\p{L}_][\\p{L}_\\p{N}\\p{M}]*\\k)\n\t\t\t\t\t\t\t\t\t\t\\s+\n\t\t\t\t\t\t\t\t\t\t(((?`?)[\\p{L}_][\\p{L}_\\p{N}\\p{M}]*\\k))\n\t\t\t\t\t\t\t\t\t\t\\s*(:)" + "patterns": [ + { + "include": "#available-types" + } + ] }, { "begin": "(((?`?)[\\p{L}_][\\p{L}_\\p{N}\\p{M}]*\\k))\\s*(:)", @@ -2279,7 +2324,7 @@ "name": "constant.numeric.swift" } }, - "match": "\\s*\\b((?:iOS|macOS|OSX|watchOS|tvOS)(?:ApplicationExtension)?)\\b(?:\\s+([0-9]+(?:\\.[0-9]+)*\\b))" + "match": "\\s*\\b((?:iOS|macOS|OSX|watchOS|tvOS|UIKitForMac)(?:ApplicationExtension)?)\\b(?:\\s+([0-9]+(?:\\.[0-9]+)*\\b))" }, { "captures": { diff --git a/extensions/theme-abyss/package.json b/extensions/theme-abyss/package.json index 2d6e6962c25..bdeb6a2a643 100644 --- a/extensions/theme-abyss/package.json +++ b/extensions/theme-abyss/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "contributes": { "themes": [ diff --git a/extensions/theme-abyss/themes/abyss-color-theme.json b/extensions/theme-abyss/themes/abyss-color-theme.json index d74d3d57ed5..43a3ae648dc 100644 --- a/extensions/theme-abyss/themes/abyss-color-theme.json +++ b/extensions/theme-abyss/themes/abyss-color-theme.json @@ -86,7 +86,9 @@ "name": "Class name", "scope": [ "entity.name.class", - "entity.name.type" + "entity.name.type", + "entity.name.namespace", + "entity.name.scope-resolution" ], "settings": { "fontStyle": "underline", @@ -400,6 +402,7 @@ "statusBar.noFolderBackground": "#10192c", "statusBar.debuggingBackground": "#10192c", // "statusBar.foreground": "", + "statusBarItem.remoteBackground": "#0063a5", "statusBarItem.prominentBackground": "#0063a5", "statusBarItem.prominentHoverBackground": "#0063a5dd", // "statusBarItem.activeBackground": "", diff --git a/extensions/theme-defaults/fileicons/images/Document_16x.svg b/extensions/theme-defaults/fileicons/images/Document_16x.svg deleted file mode 100644 index 46a9f38cc88..00000000000 --- a/extensions/theme-defaults/fileicons/images/Document_16x.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extensions/theme-defaults/fileicons/images/Document_16x_inverse.svg b/extensions/theme-defaults/fileicons/images/Document_16x_inverse.svg deleted file mode 100755 index 14abfb51077..00000000000 --- a/extensions/theme-defaults/fileicons/images/Document_16x_inverse.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extensions/theme-defaults/fileicons/images/FolderOpen_16x.svg b/extensions/theme-defaults/fileicons/images/FolderOpen_16x.svg deleted file mode 100644 index 1a3933d6351..00000000000 --- a/extensions/theme-defaults/fileicons/images/FolderOpen_16x.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extensions/theme-defaults/fileicons/images/FolderOpen_16x_inverse.svg b/extensions/theme-defaults/fileicons/images/FolderOpen_16x_inverse.svg deleted file mode 100755 index fbf57c927f2..00000000000 --- a/extensions/theme-defaults/fileicons/images/FolderOpen_16x_inverse.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extensions/theme-defaults/fileicons/images/Folder_16x.svg b/extensions/theme-defaults/fileicons/images/Folder_16x.svg deleted file mode 100644 index 3d64ae71db4..00000000000 --- a/extensions/theme-defaults/fileicons/images/Folder_16x.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extensions/theme-defaults/fileicons/images/Folder_16x_inverse.svg b/extensions/theme-defaults/fileicons/images/Folder_16x_inverse.svg deleted file mode 100755 index 13b18d18016..00000000000 --- a/extensions/theme-defaults/fileicons/images/Folder_16x_inverse.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extensions/theme-defaults/fileicons/images/RootFolderOpen_16x.svg b/extensions/theme-defaults/fileicons/images/RootFolderOpen_16x.svg deleted file mode 100755 index 20460ec997b..00000000000 --- a/extensions/theme-defaults/fileicons/images/RootFolderOpen_16x.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/extensions/theme-defaults/fileicons/images/RootFolderOpen_16x_inverse.svg b/extensions/theme-defaults/fileicons/images/RootFolderOpen_16x_inverse.svg deleted file mode 100755 index d1a0fb04b70..00000000000 --- a/extensions/theme-defaults/fileicons/images/RootFolderOpen_16x_inverse.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/extensions/theme-defaults/fileicons/images/RootFolder_16x.svg b/extensions/theme-defaults/fileicons/images/RootFolder_16x.svg deleted file mode 100755 index 9a049f6237a..00000000000 --- a/extensions/theme-defaults/fileicons/images/RootFolder_16x.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/extensions/theme-defaults/fileicons/images/RootFolder_16x_inverse.svg b/extensions/theme-defaults/fileicons/images/RootFolder_16x_inverse.svg deleted file mode 100755 index 03721272942..00000000000 --- a/extensions/theme-defaults/fileicons/images/RootFolder_16x_inverse.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/extensions/theme-defaults/fileicons/images/document-dark.svg b/extensions/theme-defaults/fileicons/images/document-dark.svg new file mode 100644 index 00000000000..5ed5762a1f0 --- /dev/null +++ b/extensions/theme-defaults/fileicons/images/document-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/theme-defaults/fileicons/images/document-light.svg b/extensions/theme-defaults/fileicons/images/document-light.svg new file mode 100644 index 00000000000..ad54e13b1b1 --- /dev/null +++ b/extensions/theme-defaults/fileicons/images/document-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/theme-defaults/fileicons/images/folder-dark.svg b/extensions/theme-defaults/fileicons/images/folder-dark.svg new file mode 100644 index 00000000000..43d454e7e5a --- /dev/null +++ b/extensions/theme-defaults/fileicons/images/folder-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/theme-defaults/fileicons/images/folder-light.svg b/extensions/theme-defaults/fileicons/images/folder-light.svg new file mode 100644 index 00000000000..8daecdac6a3 --- /dev/null +++ b/extensions/theme-defaults/fileicons/images/folder-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/theme-defaults/fileicons/images/folder-open-dark.svg b/extensions/theme-defaults/fileicons/images/folder-open-dark.svg new file mode 100644 index 00000000000..6bc1c584e48 --- /dev/null +++ b/extensions/theme-defaults/fileicons/images/folder-open-dark.svg @@ -0,0 +1,4 @@ + + + + diff --git a/extensions/theme-defaults/fileicons/images/folder-open-light.svg b/extensions/theme-defaults/fileicons/images/folder-open-light.svg new file mode 100644 index 00000000000..0a50339b6c8 --- /dev/null +++ b/extensions/theme-defaults/fileicons/images/folder-open-light.svg @@ -0,0 +1,4 @@ + + + + diff --git a/extensions/theme-defaults/fileicons/images/root-folder-dark.svg b/extensions/theme-defaults/fileicons/images/root-folder-dark.svg new file mode 100644 index 00000000000..cdb770c86a8 --- /dev/null +++ b/extensions/theme-defaults/fileicons/images/root-folder-dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/theme-defaults/fileicons/images/root-folder-light.svg b/extensions/theme-defaults/fileicons/images/root-folder-light.svg new file mode 100644 index 00000000000..82a0294696f --- /dev/null +++ b/extensions/theme-defaults/fileicons/images/root-folder-light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/theme-defaults/fileicons/images/root-folder-open-dark.svg b/extensions/theme-defaults/fileicons/images/root-folder-open-dark.svg new file mode 100644 index 00000000000..472def3daa1 --- /dev/null +++ b/extensions/theme-defaults/fileicons/images/root-folder-open-dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/theme-defaults/fileicons/images/root-folder-open-light.svg b/extensions/theme-defaults/fileicons/images/root-folder-open-light.svg new file mode 100644 index 00000000000..d2363bfae35 --- /dev/null +++ b/extensions/theme-defaults/fileicons/images/root-folder-open-light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/theme-defaults/fileicons/vs_minimal-icon-theme.json b/extensions/theme-defaults/fileicons/vs_minimal-icon-theme.json index 9c9f60b6efc..7a178065380 100644 --- a/extensions/theme-defaults/fileicons/vs_minimal-icon-theme.json +++ b/extensions/theme-defaults/fileicons/vs_minimal-icon-theme.json @@ -1,34 +1,34 @@ { "iconDefinitions": { "_root_folder_dark": { - "iconPath": "./images/RootFolder_16x_inverse.svg" + "iconPath": "./images/root-folder-dark.svg" }, "_root_folder_open_dark": { - "iconPath": "./images/RootFolderOpen_16x_inverse.svg" + "iconPath": "./images/root-folder-open-dark.svg" }, "_folder_dark": { - "iconPath": "./images/Folder_16x_inverse.svg" + "iconPath": "./images/folder-dark.svg" }, "_folder_open_dark": { - "iconPath": "./images/FolderOpen_16x_inverse.svg" + "iconPath": "./images/folder-open-dark.svg" }, "_file_dark": { - "iconPath": "./images/Document_16x_inverse.svg" + "iconPath": "./images/document-dark.svg" }, "_root_folder": { - "iconPath": "./images/RootFolder_16x.svg" + "iconPath": "./images/root-folder-light.svg" }, "_root_folder_open": { - "iconPath": "./images/RootFolderOpen_16x.svg" + "iconPath": "./images/root-folder-open-light.svg" }, "_folder_light": { - "iconPath": "./images/Folder_16x.svg" + "iconPath": "./images/folder-light.svg" }, "_folder_open_light": { - "iconPath": "./images/FolderOpen_16x.svg" + "iconPath": "./images/folder-open-light.svg" }, "_file_light": { - "iconPath": "./images/Document_16x.svg" + "iconPath": "./images/document-light.svg" } }, diff --git a/extensions/theme-defaults/package.json b/extensions/theme-defaults/package.json index bbc13a472ba..56d5fa3f4b1 100644 --- a/extensions/theme-defaults/package.json +++ b/extensions/theme-defaults/package.json @@ -5,6 +5,7 @@ "categories": [ "Themes" ], "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "contributes": { "themes": [ diff --git a/extensions/theme-defaults/themes/dark_defaults.json b/extensions/theme-defaults/themes/dark_defaults.json index 276a71d0fdb..00c2ac8c36b 100644 --- a/extensions/theme-defaults/themes/dark_defaults.json +++ b/extensions/theme-defaults/themes/dark_defaults.json @@ -15,6 +15,8 @@ "settings.textInputBackground": "#292929", "settings.numberInputBackground": "#292929", "menu.background": "#252526", - "menu.foreground": "#CCCCCC" + "menu.foreground": "#CCCCCC", + "statusBarItem.remoteForeground": "#FFF", + "statusBarItem.remoteBackground": "#16825D" } } \ No newline at end of file diff --git a/extensions/theme-defaults/themes/dark_plus.json b/extensions/theme-defaults/themes/dark_plus.json index 3e2c5ac607c..f12d3d7633e 100644 --- a/extensions/theme-defaults/themes/dark_plus.json +++ b/extensions/theme-defaults/themes/dark_plus.json @@ -8,7 +8,8 @@ "scope": [ "entity.name.function", "support.function", - "support.constant.handlebars" + "support.constant.handlebars", + "source.powershell variable.other.member" ], "settings": { "foreground": "#DCDCAA" @@ -21,6 +22,8 @@ "support.class", "support.type", "entity.name.type", + "entity.name.namespace", + "entity.name.scope-resolution", "entity.name.class", "storage.type.numeric.go", "storage.type.byte.go", @@ -67,8 +70,14 @@ } }, { - "name": "Control flow keywords", - "scope": "keyword.control", + "name": "Control flow / Special keywords", + "scope": [ + "keyword.control", + "source.cpp keyword.operator.new", + "keyword.operator.delete", + "keyword.other.using", + "keyword.other.operator" + ], "settings": { "foreground": "#C586C0" } @@ -163,4 +172,4 @@ } } ] -} \ No newline at end of file +} diff --git a/extensions/theme-defaults/themes/hc_black.json b/extensions/theme-defaults/themes/hc_black.json index c34b0981fd6..f76d7bb960f 100644 --- a/extensions/theme-defaults/themes/hc_black.json +++ b/extensions/theme-defaults/themes/hc_black.json @@ -4,7 +4,8 @@ "include": "./hc_black_defaults.json", "colors": { "selection.background": "#008000", - "editor.selectionBackground": "#FFFFFF" + "editor.selectionBackground": "#FFFFFF", + "statusBarItem.remoteBackground": "#00000000" }, "tokenColors": [ { @@ -12,7 +13,8 @@ "scope": [ "entity.name.function", "support.function", - "support.constant.handlebars" + "support.constant.handlebars", + "source.powershell variable.other.member" ], "settings": { "foreground": "#DCDCAA" @@ -25,6 +27,8 @@ "support.class", "support.type", "entity.name.type", + "entity.name.namespace", + "entity.name.scope-resolution", "entity.name.class", "storage.type.cs", "storage.type.generic.cs", @@ -64,8 +68,14 @@ } }, { - "name": "Control flow keywords", - "scope": "keyword.control", + "name": "Control flow / Special keywords", + "scope": [ + "keyword.control", + "source.cpp keyword.operator.new", + "source.cpp keyword.operator.delete", + "keyword.other.using", + "keyword.other.operator" + ], "settings": { "foreground": "#C586C0" } @@ -106,4 +116,4 @@ } } ] -} \ No newline at end of file +} diff --git a/extensions/theme-defaults/themes/hc_black_defaults.json b/extensions/theme-defaults/themes/hc_black_defaults.json index 932ebabbbc8..9d11138a99b 100644 --- a/extensions/theme-defaults/themes/hc_black_defaults.json +++ b/extensions/theme-defaults/themes/hc_black_defaults.json @@ -6,6 +6,7 @@ "editor.foreground": "#FFFFFF", "editorIndentGuide.background": "#FFFFFF", "editorIndentGuide.activeBackground": "#FFFFFF", + "statusBarItem.remoteBackground": "#00000000", "sideBarTitle.foreground": "#FFFFFF" }, "settings": [ diff --git a/extensions/theme-defaults/themes/light_defaults.json b/extensions/theme-defaults/themes/light_defaults.json index 91c5fb1d93a..e28c9b8ed0b 100644 --- a/extensions/theme-defaults/themes/light_defaults.json +++ b/extensions/theme-defaults/themes/light_defaults.json @@ -14,6 +14,8 @@ "list.hoverBackground": "#E8E8E8", "input.placeholderForeground": "#767676", "settings.textInputBorder": "#CECECE", - "settings.numberInputBorder": "#CECECE" + "settings.numberInputBorder": "#CECECE", + "statusBarItem.remoteForeground": "#FFF", + "statusBarItem.remoteBackground": "#16825D" } } \ No newline at end of file diff --git a/extensions/theme-defaults/themes/light_plus.json b/extensions/theme-defaults/themes/light_plus.json index 726cae4058d..3d30c5d17fb 100644 --- a/extensions/theme-defaults/themes/light_plus.json +++ b/extensions/theme-defaults/themes/light_plus.json @@ -8,7 +8,8 @@ "scope": [ "entity.name.function", "support.function", - "support.constant.handlebars" + "support.constant.handlebars", + "source.powershell variable.other.member" ], "settings": { "foreground": "#795E26" @@ -21,6 +22,8 @@ "support.class", "support.type", "entity.name.type", + "entity.name.namespace", + "entity.name.scope-resolution", "entity.name.class", "storage.type.numeric.go", "storage.type.byte.go", @@ -67,8 +70,14 @@ } }, { - "name": "Control flow keywords", - "scope": "keyword.control", + "name": "Control flow / Special keywords", + "scope": [ + "keyword.control", + "source.cpp keyword.operator.new", + "source.cpp keyword.operator.delete", + "keyword.other.using", + "keyword.other.operator" + ], "settings": { "foreground": "#AF00DB" } @@ -164,4 +173,4 @@ } ] -} \ No newline at end of file +} diff --git a/extensions/theme-kimbie-dark/package.json b/extensions/theme-kimbie-dark/package.json index 06682901e02..1031c34d2e7 100644 --- a/extensions/theme-kimbie-dark/package.json +++ b/extensions/theme-kimbie-dark/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "contributes": { "themes": [ diff --git a/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json b/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json index d4fbd2f7e2e..4b0eb5bdfcf 100644 --- a/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json +++ b/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json @@ -27,6 +27,7 @@ "statusBar.background": "#423523", "statusBar.debuggingBackground": "#423523", "statusBar.noFolderBackground": "#423523", + "statusBarItem.remoteBackground": "#6e583b", "activityBar.background": "#221a0f", "activityBar.foreground": "#d3af86", "sideBar.background": "#362712", @@ -113,7 +114,11 @@ "name": "Keywords", "scope": [ "keyword", - "keyword.control" + "keyword.control", + "keyword.operator.new.cpp", + "keyword.operator.delete.cpp", + "keyword.other.using", + "keyword.other.operator" ], "settings": { "foreground": "#98676a" @@ -142,7 +147,9 @@ "scope": [ "support.class", "entity.name.class", - "entity.name.type" + "entity.name.type", + "entity.name.namespace", + "entity.name.scope-resolution" ], "settings": { "foreground": "#f06431" diff --git a/extensions/theme-monokai-dimmed/package.json b/extensions/theme-monokai-dimmed/package.json index f64721a898f..66c4711d9ab 100644 --- a/extensions/theme-monokai-dimmed/package.json +++ b/extensions/theme-monokai-dimmed/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, diff --git a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json index b50041d6cdd..5f5e5cff916 100644 --- a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json +++ b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json @@ -31,6 +31,7 @@ "statusBar.debuggingBackground": "#505050", "statusBar.noFolderBackground": "#505050", "titleBar.activeBackground": "#505050", + "statusBarItem.remoteBackground": "#3655b5", "activityBar.background": "#353535", "activityBar.foreground": "#ffffff", "activityBarBadge.background": "#3655b5", @@ -142,7 +143,7 @@ }, { "name": "Class name", - "scope": "entity.name.class, entity.name.type", + "scope": "entity.name.class, entity.name.type, entity.name.namespace, entity.name.scope-resolution", "settings": { "fontStyle": "", "foreground": "#9B0000", @@ -254,8 +255,14 @@ } }, { - "name": "Keyword Control", - "scope": "keyword.control", + "name": "Keyword Control / Special", + "scope": [ + "keyword.control", + "keyword.operator.new.cpp", + "keyword.operator.delete.cpp", + "keyword.other.using", + "keyword.other.operator" + ], "settings": { "fontStyle": "", "foreground": "#9872A2" diff --git a/extensions/theme-monokai/package.json b/extensions/theme-monokai/package.json index 550f22933d3..13b2db10d00 100644 --- a/extensions/theme-monokai/package.json +++ b/extensions/theme-monokai/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, diff --git a/extensions/theme-monokai/themes/monokai-color-theme.json b/extensions/theme-monokai/themes/monokai-color-theme.json index 3806508775a..c16fa3c5575 100644 --- a/extensions/theme-monokai/themes/monokai-color-theme.json +++ b/extensions/theme-monokai/themes/monokai-color-theme.json @@ -23,8 +23,8 @@ "selection.background": "#ccccc7", "editor.selectionHighlightBackground": "#575b6180", "editor.selectionBackground": "#878b9180", - "editor.wordHighlightBackground": "#4a4a7680", - "editor.wordHighlightStrongBackground": "#6a6a9680", + "editor.wordHighlightBackground": "#4a4a7680", + "editor.wordHighlightStrongBackground": "#6a6a9680", "editor.lineHighlightBackground": "#3e3d32", "editorLineNumber.activeForeground": "#c2c2bf", "editorCursor.foreground": "#f8f8f0", @@ -50,6 +50,7 @@ "statusBar.background": "#414339", "statusBar.noFolderBackground": "#414339", "statusBar.debuggingBackground": "#75715E", + "statusBarItem.remoteBackground": "#AC6218", "activityBar.background": "#272822", "activityBar.foreground": "#f8f8f2", "activityBar.dropBackground": "#414339", @@ -204,7 +205,7 @@ }, { "name": "Class name", - "scope": "entity.name.type, entity.name.class", + "scope": "entity.name.type, entity.name.class, entity.name.namespace, entity.name.scope-resolution", "settings": { "fontStyle": "underline", "foreground": "#A6E22E" diff --git a/extensions/theme-quietlight/package.json b/extensions/theme-quietlight/package.json index 0620f730886..0263925eee8 100644 --- a/extensions/theme-quietlight/package.json +++ b/extensions/theme-quietlight/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, diff --git a/extensions/theme-quietlight/themes/quietlight-color-theme.json b/extensions/theme-quietlight/themes/quietlight-color-theme.json index 2cef3aa273f..38681612b42 100644 --- a/extensions/theme-quietlight/themes/quietlight-color-theme.json +++ b/extensions/theme-quietlight/themes/quietlight-color-theme.json @@ -125,6 +125,8 @@ "name": "Classes", "scope": [ "entity.name.type", + "entity.name.namespace", + "entity.name.scope-resolution", "entity.other.inherited-class", "support.class" ], @@ -516,6 +518,7 @@ "statusBar.background": "#705697", "statusBar.noFolderBackground": "#705697", "statusBar.debuggingBackground": "#705697", + "statusBarItem.remoteBackground": "#4e3c69", "activityBar.background": "#EDEDF5", "activityBar.foreground": "#705697", "activityBarBadge.background": "#705697", diff --git a/extensions/theme-red/package.json b/extensions/theme-red/package.json index 4b4f294fc5a..ba751a33e42 100644 --- a/extensions/theme-red/package.json +++ b/extensions/theme-red/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "contributes": { "themes": [ diff --git a/extensions/theme-red/themes/Red-color-theme.json b/extensions/theme-red/themes/Red-color-theme.json index 3de9575b0db..18e5786a8f3 100644 --- a/extensions/theme-red/themes/Red-color-theme.json +++ b/extensions/theme-red/themes/Red-color-theme.json @@ -9,6 +9,7 @@ "sideBar.background": "#330000", "statusBar.background": "#700000", "statusBar.noFolderBackground": "#700000", + "statusBarItem.remoteBackground": "#c33", "editorGroupHeader.tabsBackground": "#330000", "titleBar.activeBackground": "#770000", "titleBar.inactiveBackground": "#772222", diff --git a/extensions/theme-seti/build/update-icon-theme.js b/extensions/theme-seti/build/update-icon-theme.js index 4c05d551c62..6819e853339 100644 --- a/extensions/theme-seti/build/update-icon-theme.js +++ b/extensions/theme-seti/build/update-icon-theme.js @@ -10,7 +10,7 @@ let fs = require('fs'); let https = require('https'); let url = require('url'); -// list of languagesIs not shipped with VSCode. The information is used to associate an icon with a langauge association +// list of languagesIs not shipped with VSCode. The information is used to associate an icon with a language association let nonBuiltInLanguages = { // { fileNames, extensions } "r": { extensions: ['r', 'rhistory', 'rprofile', 'rt'] }, "argdown": { extensions: ['ad', 'adown', 'argdown', 'argdn'] }, @@ -35,7 +35,7 @@ let nonBuiltInLanguages = { // { fileNames, extensions } "todo": { fileNames: ['todo'] } }; -let FROM_DISK = false; // set to true to take content from a repo checkedout next to the vscode repo +let FROM_DISK = true; // set to true to take content from a repo checked out next to the vscode repo let font, fontMappingsFile, fileAssociationFile, colorsFile; if (!FROM_DISK) { @@ -163,7 +163,7 @@ function darkenColor(color) { for (let i = 1; i < 7; i += 2) { let newVal = Math.round(parseInt('0x' + color.substr(i, 2), 16) * 0.9); let hex = newVal.toString(16); - if (hex.length == 1) { + if (hex.length === 1) { res += '0'; } res += hex; diff --git a/extensions/theme-seti/cgmanifest.json b/extensions/theme-seti/cgmanifest.json index 2b449830f50..c742c019ea3 100644 --- a/extensions/theme-seti/cgmanifest.json +++ b/extensions/theme-seti/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "seti-ui", "repositoryUrl": "https://github.com/jesseweed/seti-ui", - "commitHash": "89175d7f9e0c70cd325b80a18a3c77fc8eb7c798" + "commitHash": "904c16acced1134a81b31d71d60293288c31334b" } }, "version": "0.1.0" diff --git a/extensions/theme-seti/icons/seti.woff b/extensions/theme-seti/icons/seti.woff index e590d77f684..b85727d01e4 100644 Binary files a/extensions/theme-seti/icons/seti.woff and b/extensions/theme-seti/icons/seti.woff differ diff --git a/extensions/theme-seti/icons/vs-seti-icon-theme.json b/extensions/theme-seti/icons/vs-seti-icon-theme.json index 4aec2074092..52a81da4596 100644 --- a/extensions/theme-seti/icons/vs-seti-icon-theme.json +++ b/extensions/theme-seti/icons/vs-seti-icon-theme.json @@ -206,6 +206,14 @@ "fontCharacter": "\\E017", "fontColor": "#a074c4" }, + "_cpp_2_light": { + "fontCharacter": "\\E017", + "fontColor": "#b7b73b" + }, + "_cpp_2": { + "fontCharacter": "\\E017", + "fontColor": "#cbcb41" + }, "_crystal_light": { "fontCharacter": "\\E018", "fontColor": "#bfc2c1" @@ -246,999 +254,1103 @@ "fontCharacter": "\\E01C", "fontColor": "#cc3e44" }, - "_db_light": { + "_dart_light": { "fontCharacter": "\\E01D", + "fontColor": "#498ba7" + }, + "_dart": { + "fontCharacter": "\\E01D", + "fontColor": "#519aba" + }, + "_db_light": { + "fontCharacter": "\\E01E", "fontColor": "#dd4b78" }, "_db": { - "fontCharacter": "\\E01D", + "fontCharacter": "\\E01E", "fontColor": "#f55385" }, "_default_light": { - "fontCharacter": "\\E01E", + "fontCharacter": "\\E01F", "fontColor": "#bfc2c1" }, "_default": { - "fontCharacter": "\\E01E", + "fontCharacter": "\\E01F", "fontColor": "#d4d7d6" }, "_docker_light": { - "fontCharacter": "\\E020", + "fontCharacter": "\\E021", "fontColor": "#498ba7" }, "_docker": { - "fontCharacter": "\\E020", + "fontCharacter": "\\E021", "fontColor": "#519aba" }, "_docker_1_light": { - "fontCharacter": "\\E020", + "fontCharacter": "\\E021", "fontColor": "#455155" }, "_docker_1": { - "fontCharacter": "\\E020", + "fontCharacter": "\\E021", "fontColor": "#4d5a5e" }, "_docker_2_light": { - "fontCharacter": "\\E020", + "fontCharacter": "\\E021", "fontColor": "#7fae42" }, "_docker_2": { - "fontCharacter": "\\E020", + "fontCharacter": "\\E021", "fontColor": "#8dc149" }, "_docker_3_light": { - "fontCharacter": "\\E020", + "fontCharacter": "\\E021", "fontColor": "#dd4b78" }, "_docker_3": { - "fontCharacter": "\\E020", + "fontCharacter": "\\E021", "fontColor": "#f55385" }, "_ejs_light": { - "fontCharacter": "\\E022", + "fontCharacter": "\\E023", "fontColor": "#b7b73b" }, "_ejs": { - "fontCharacter": "\\E022", + "fontCharacter": "\\E023", "fontColor": "#cbcb41" }, "_elixir_light": { - "fontCharacter": "\\E023", + "fontCharacter": "\\E024", "fontColor": "#9068b0" }, "_elixir": { - "fontCharacter": "\\E023", + "fontCharacter": "\\E024", "fontColor": "#a074c4" }, "_elixir_script_light": { - "fontCharacter": "\\E024", + "fontCharacter": "\\E025", "fontColor": "#9068b0" }, "_elixir_script": { - "fontCharacter": "\\E024", + "fontCharacter": "\\E025", "fontColor": "#a074c4" }, "_elm_light": { - "fontCharacter": "\\E025", + "fontCharacter": "\\E026", "fontColor": "#498ba7" }, "_elm": { - "fontCharacter": "\\E025", + "fontCharacter": "\\E026", "fontColor": "#519aba" }, "_eslint_light": { - "fontCharacter": "\\E027", + "fontCharacter": "\\E028", "fontColor": "#9068b0" }, "_eslint": { - "fontCharacter": "\\E027", + "fontCharacter": "\\E028", "fontColor": "#a074c4" }, "_eslint_1_light": { - "fontCharacter": "\\E027", + "fontCharacter": "\\E028", "fontColor": "#455155" }, "_eslint_1": { - "fontCharacter": "\\E027", + "fontCharacter": "\\E028", "fontColor": "#4d5a5e" }, "_ethereum_light": { - "fontCharacter": "\\E028", + "fontCharacter": "\\E029", "fontColor": "#498ba7" }, "_ethereum": { - "fontCharacter": "\\E028", + "fontCharacter": "\\E029", "fontColor": "#519aba" }, "_f-sharp_light": { - "fontCharacter": "\\E029", + "fontCharacter": "\\E02A", "fontColor": "#498ba7" }, "_f-sharp": { - "fontCharacter": "\\E029", + "fontCharacter": "\\E02A", "fontColor": "#519aba" }, "_favicon_light": { - "fontCharacter": "\\E02A", + "fontCharacter": "\\E02B", "fontColor": "#b7b73b" }, "_favicon": { - "fontCharacter": "\\E02A", + "fontCharacter": "\\E02B", "fontColor": "#cbcb41" }, "_firebase_light": { - "fontCharacter": "\\E02B", + "fontCharacter": "\\E02C", "fontColor": "#cc6d2e" }, "_firebase": { - "fontCharacter": "\\E02B", + "fontCharacter": "\\E02C", "fontColor": "#e37933" }, "_firefox_light": { - "fontCharacter": "\\E02C", + "fontCharacter": "\\E02D", "fontColor": "#cc6d2e" }, "_firefox": { - "fontCharacter": "\\E02C", + "fontCharacter": "\\E02D", "fontColor": "#e37933" }, "_font_light": { - "fontCharacter": "\\E02E", + "fontCharacter": "\\E02F", "fontColor": "#b8383d" }, "_font": { - "fontCharacter": "\\E02E", + "fontCharacter": "\\E02F", "fontColor": "#cc3e44" }, "_git_light": { - "fontCharacter": "\\E02F", + "fontCharacter": "\\E030", "fontColor": "#3b4b52" }, "_git": { - "fontCharacter": "\\E02F", + "fontCharacter": "\\E030", "fontColor": "#41535b" }, "_go_light": { - "fontCharacter": "\\E033", + "fontCharacter": "\\E034", "fontColor": "#498ba7" }, "_go": { - "fontCharacter": "\\E033", + "fontCharacter": "\\E034", "fontColor": "#519aba" }, "_go2_light": { - "fontCharacter": "\\E034", + "fontCharacter": "\\E035", "fontColor": "#498ba7" }, "_go2": { - "fontCharacter": "\\E034", + "fontCharacter": "\\E035", "fontColor": "#519aba" }, "_gradle_light": { - "fontCharacter": "\\E035", + "fontCharacter": "\\E036", "fontColor": "#7fae42" }, "_gradle": { - "fontCharacter": "\\E035", + "fontCharacter": "\\E036", "fontColor": "#8dc149" }, "_grails_light": { - "fontCharacter": "\\E036", + "fontCharacter": "\\E037", "fontColor": "#7fae42" }, "_grails": { - "fontCharacter": "\\E036", + "fontCharacter": "\\E037", "fontColor": "#8dc149" }, + "_graphql_light": { + "fontCharacter": "\\E038", + "fontColor": "#dd4b78" + }, + "_graphql": { + "fontCharacter": "\\E038", + "fontColor": "#f55385" + }, "_grunt_light": { - "fontCharacter": "\\E037", + "fontCharacter": "\\E039", "fontColor": "#cc6d2e" }, "_grunt": { - "fontCharacter": "\\E037", + "fontCharacter": "\\E039", "fontColor": "#e37933" }, "_gulp_light": { - "fontCharacter": "\\E038", + "fontCharacter": "\\E03A", "fontColor": "#b8383d" }, "_gulp": { - "fontCharacter": "\\E038", + "fontCharacter": "\\E03A", "fontColor": "#cc3e44" }, "_haml_light": { - "fontCharacter": "\\E03A", + "fontCharacter": "\\E03C", "fontColor": "#b8383d" }, "_haml": { - "fontCharacter": "\\E03A", + "fontCharacter": "\\E03C", "fontColor": "#cc3e44" }, + "_happenings_light": { + "fontCharacter": "\\E03D", + "fontColor": "#498ba7" + }, + "_happenings": { + "fontCharacter": "\\E03D", + "fontColor": "#519aba" + }, "_haskell_light": { - "fontCharacter": "\\E03B", + "fontCharacter": "\\E03E", "fontColor": "#9068b0" }, "_haskell": { - "fontCharacter": "\\E03B", + "fontCharacter": "\\E03E", "fontColor": "#a074c4" }, "_haxe_light": { - "fontCharacter": "\\E03C", + "fontCharacter": "\\E03F", "fontColor": "#cc6d2e" }, "_haxe": { - "fontCharacter": "\\E03C", + "fontCharacter": "\\E03F", "fontColor": "#e37933" }, "_haxe_1_light": { - "fontCharacter": "\\E03C", + "fontCharacter": "\\E03F", "fontColor": "#b7b73b" }, "_haxe_1": { - "fontCharacter": "\\E03C", + "fontCharacter": "\\E03F", "fontColor": "#cbcb41" }, "_haxe_2_light": { - "fontCharacter": "\\E03C", + "fontCharacter": "\\E03F", "fontColor": "#498ba7" }, "_haxe_2": { - "fontCharacter": "\\E03C", + "fontCharacter": "\\E03F", "fontColor": "#519aba" }, "_haxe_3_light": { - "fontCharacter": "\\E03C", + "fontCharacter": "\\E03F", "fontColor": "#9068b0" }, "_haxe_3": { - "fontCharacter": "\\E03C", + "fontCharacter": "\\E03F", "fontColor": "#a074c4" }, "_heroku_light": { - "fontCharacter": "\\E03D", + "fontCharacter": "\\E040", "fontColor": "#9068b0" }, "_heroku": { - "fontCharacter": "\\E03D", + "fontCharacter": "\\E040", "fontColor": "#a074c4" }, "_hex_light": { - "fontCharacter": "\\E03E", + "fontCharacter": "\\E041", "fontColor": "#b8383d" }, "_hex": { - "fontCharacter": "\\E03E", + "fontCharacter": "\\E041", "fontColor": "#cc3e44" }, "_html_light": { - "fontCharacter": "\\E03F", - "fontColor": "#cc6d2e" + "fontCharacter": "\\E042", + "fontColor": "#498ba7" }, "_html": { - "fontCharacter": "\\E03F", + "fontCharacter": "\\E042", + "fontColor": "#519aba" + }, + "_html_1_light": { + "fontCharacter": "\\E042", + "fontColor": "#7fae42" + }, + "_html_1": { + "fontCharacter": "\\E042", + "fontColor": "#8dc149" + }, + "_html_2_light": { + "fontCharacter": "\\E042", + "fontColor": "#b7b73b" + }, + "_html_2": { + "fontCharacter": "\\E042", + "fontColor": "#cbcb41" + }, + "_html_3_light": { + "fontCharacter": "\\E042", + "fontColor": "#cc6d2e" + }, + "_html_3": { + "fontCharacter": "\\E042", "fontColor": "#e37933" }, "_html_erb_light": { - "fontCharacter": "\\E040", + "fontCharacter": "\\E043", "fontColor": "#b8383d" }, "_html_erb": { - "fontCharacter": "\\E040", + "fontCharacter": "\\E043", "fontColor": "#cc3e44" }, "_ignored_light": { - "fontCharacter": "\\E041", + "fontCharacter": "\\E044", "fontColor": "#3b4b52" }, "_ignored": { - "fontCharacter": "\\E041", + "fontCharacter": "\\E044", "fontColor": "#41535b" }, "_illustrator_light": { - "fontCharacter": "\\E042", + "fontCharacter": "\\E045", "fontColor": "#b7b73b" }, "_illustrator": { - "fontCharacter": "\\E042", + "fontCharacter": "\\E045", "fontColor": "#cbcb41" }, "_image_light": { - "fontCharacter": "\\E043", + "fontCharacter": "\\E046", "fontColor": "#9068b0" }, "_image": { - "fontCharacter": "\\E043", + "fontCharacter": "\\E046", "fontColor": "#a074c4" }, "_info_light": { - "fontCharacter": "\\E044", + "fontCharacter": "\\E047", "fontColor": "#498ba7" }, "_info": { - "fontCharacter": "\\E044", + "fontCharacter": "\\E047", "fontColor": "#519aba" }, "_ionic_light": { - "fontCharacter": "\\E045", + "fontCharacter": "\\E048", "fontColor": "#498ba7" }, "_ionic": { - "fontCharacter": "\\E045", + "fontCharacter": "\\E048", "fontColor": "#519aba" }, "_jade_light": { - "fontCharacter": "\\E046", + "fontCharacter": "\\E049", "fontColor": "#b8383d" }, "_jade": { - "fontCharacter": "\\E046", + "fontCharacter": "\\E049", "fontColor": "#cc3e44" }, "_java_light": { - "fontCharacter": "\\E047", + "fontCharacter": "\\E04A", "fontColor": "#b8383d" }, "_java": { - "fontCharacter": "\\E047", + "fontCharacter": "\\E04A", "fontColor": "#cc3e44" }, "_javascript_light": { - "fontCharacter": "\\E048", + "fontCharacter": "\\E04B", "fontColor": "#b7b73b" }, "_javascript": { - "fontCharacter": "\\E048", + "fontCharacter": "\\E04B", "fontColor": "#cbcb41" }, "_javascript_1_light": { - "fontCharacter": "\\E048", + "fontCharacter": "\\E04B", "fontColor": "#cc6d2e" }, "_javascript_1": { - "fontCharacter": "\\E048", + "fontCharacter": "\\E04B", "fontColor": "#e37933" }, "_javascript_2_light": { - "fontCharacter": "\\E048", + "fontCharacter": "\\E04B", "fontColor": "#498ba7" }, "_javascript_2": { - "fontCharacter": "\\E048", + "fontCharacter": "\\E04B", "fontColor": "#519aba" }, "_jenkins_light": { - "fontCharacter": "\\E049", + "fontCharacter": "\\E04C", "fontColor": "#b8383d" }, "_jenkins": { - "fontCharacter": "\\E049", + "fontCharacter": "\\E04C", "fontColor": "#cc3e44" }, "_jinja_light": { - "fontCharacter": "\\E04A", + "fontCharacter": "\\E04D", "fontColor": "#b8383d" }, "_jinja": { - "fontCharacter": "\\E04A", + "fontCharacter": "\\E04D", "fontColor": "#cc3e44" }, "_json_light": { - "fontCharacter": "\\E04C", + "fontCharacter": "\\E04F", "fontColor": "#b7b73b" }, "_json": { - "fontCharacter": "\\E04C", + "fontCharacter": "\\E04F", "fontColor": "#cbcb41" }, "_json_1_light": { - "fontCharacter": "\\E04C", + "fontCharacter": "\\E04F", "fontColor": "#7fae42" }, "_json_1": { - "fontCharacter": "\\E04C", + "fontCharacter": "\\E04F", "fontColor": "#8dc149" }, "_julia_light": { - "fontCharacter": "\\E04D", + "fontCharacter": "\\E050", "fontColor": "#9068b0" }, "_julia": { - "fontCharacter": "\\E04D", + "fontCharacter": "\\E050", "fontColor": "#a074c4" }, "_karma_light": { - "fontCharacter": "\\E04E", + "fontCharacter": "\\E051", "fontColor": "#7fae42" }, "_karma": { - "fontCharacter": "\\E04E", + "fontCharacter": "\\E051", "fontColor": "#8dc149" }, "_kotlin_light": { - "fontCharacter": "\\E04F", + "fontCharacter": "\\E052", "fontColor": "#cc6d2e" }, "_kotlin": { - "fontCharacter": "\\E04F", + "fontCharacter": "\\E052", "fontColor": "#e37933" }, "_less_light": { - "fontCharacter": "\\E050", + "fontCharacter": "\\E053", "fontColor": "#498ba7" }, "_less": { - "fontCharacter": "\\E050", + "fontCharacter": "\\E053", "fontColor": "#519aba" }, "_license_light": { - "fontCharacter": "\\E051", + "fontCharacter": "\\E054", "fontColor": "#b7b73b" }, "_license": { - "fontCharacter": "\\E051", + "fontCharacter": "\\E054", "fontColor": "#cbcb41" }, "_license_1_light": { - "fontCharacter": "\\E051", + "fontCharacter": "\\E054", "fontColor": "#cc6d2e" }, "_license_1": { - "fontCharacter": "\\E051", + "fontCharacter": "\\E054", "fontColor": "#e37933" }, "_license_2_light": { - "fontCharacter": "\\E051", + "fontCharacter": "\\E054", "fontColor": "#b8383d" }, "_license_2": { - "fontCharacter": "\\E051", + "fontCharacter": "\\E054", "fontColor": "#cc3e44" }, "_liquid_light": { - "fontCharacter": "\\E052", + "fontCharacter": "\\E055", "fontColor": "#7fae42" }, "_liquid": { - "fontCharacter": "\\E052", + "fontCharacter": "\\E055", "fontColor": "#8dc149" }, "_livescript_light": { - "fontCharacter": "\\E053", + "fontCharacter": "\\E056", "fontColor": "#498ba7" }, "_livescript": { - "fontCharacter": "\\E053", + "fontCharacter": "\\E056", "fontColor": "#519aba" }, "_lock_light": { - "fontCharacter": "\\E054", + "fontCharacter": "\\E057", "fontColor": "#7fae42" }, "_lock": { - "fontCharacter": "\\E054", + "fontCharacter": "\\E057", "fontColor": "#8dc149" }, "_lua_light": { - "fontCharacter": "\\E055", + "fontCharacter": "\\E058", "fontColor": "#498ba7" }, "_lua": { - "fontCharacter": "\\E055", + "fontCharacter": "\\E058", "fontColor": "#519aba" }, "_makefile_light": { - "fontCharacter": "\\E056", + "fontCharacter": "\\E059", "fontColor": "#cc6d2e" }, "_makefile": { - "fontCharacter": "\\E056", + "fontCharacter": "\\E059", "fontColor": "#e37933" }, "_makefile_1_light": { - "fontCharacter": "\\E056", + "fontCharacter": "\\E059", "fontColor": "#9068b0" }, "_makefile_1": { - "fontCharacter": "\\E056", + "fontCharacter": "\\E059", "fontColor": "#a074c4" }, "_makefile_2_light": { - "fontCharacter": "\\E056", + "fontCharacter": "\\E059", "fontColor": "#627379" }, "_makefile_2": { - "fontCharacter": "\\E056", + "fontCharacter": "\\E059", "fontColor": "#6d8086" }, "_makefile_3_light": { - "fontCharacter": "\\E056", + "fontCharacter": "\\E059", "fontColor": "#498ba7" }, "_makefile_3": { - "fontCharacter": "\\E056", + "fontCharacter": "\\E059", "fontColor": "#519aba" }, "_markdown_light": { - "fontCharacter": "\\E057", + "fontCharacter": "\\E05A", "fontColor": "#498ba7" }, "_markdown": { - "fontCharacter": "\\E057", + "fontCharacter": "\\E05A", "fontColor": "#519aba" }, "_maven_light": { - "fontCharacter": "\\E058", + "fontCharacter": "\\E05B", "fontColor": "#b8383d" }, "_maven": { - "fontCharacter": "\\E058", + "fontCharacter": "\\E05B", "fontColor": "#cc3e44" }, "_mdo_light": { - "fontCharacter": "\\E059", + "fontCharacter": "\\E05C", "fontColor": "#b8383d" }, "_mdo": { - "fontCharacter": "\\E059", + "fontCharacter": "\\E05C", "fontColor": "#cc3e44" }, "_mustache_light": { - "fontCharacter": "\\E05A", + "fontCharacter": "\\E05D", "fontColor": "#cc6d2e" }, "_mustache": { - "fontCharacter": "\\E05A", + "fontCharacter": "\\E05D", "fontColor": "#e37933" }, "_npm_light": { - "fontCharacter": "\\E05C", + "fontCharacter": "\\E05F", "fontColor": "#3b4b52" }, "_npm": { - "fontCharacter": "\\E05C", + "fontCharacter": "\\E05F", "fontColor": "#41535b" }, "_npm_1_light": { - "fontCharacter": "\\E05C", + "fontCharacter": "\\E05F", "fontColor": "#b8383d" }, "_npm_1": { - "fontCharacter": "\\E05C", + "fontCharacter": "\\E05F", "fontColor": "#cc3e44" }, "_npm_ignored_light": { - "fontCharacter": "\\E05D", + "fontCharacter": "\\E060", "fontColor": "#3b4b52" }, "_npm_ignored": { - "fontCharacter": "\\E05D", + "fontCharacter": "\\E060", "fontColor": "#41535b" }, "_nunjucks_light": { - "fontCharacter": "\\E05E", + "fontCharacter": "\\E061", "fontColor": "#7fae42" }, "_nunjucks": { - "fontCharacter": "\\E05E", + "fontCharacter": "\\E061", "fontColor": "#8dc149" }, "_ocaml_light": { - "fontCharacter": "\\E05F", + "fontCharacter": "\\E062", "fontColor": "#cc6d2e" }, "_ocaml": { - "fontCharacter": "\\E05F", + "fontCharacter": "\\E062", "fontColor": "#e37933" }, "_odata_light": { - "fontCharacter": "\\E060", + "fontCharacter": "\\E063", "fontColor": "#cc6d2e" }, "_odata": { - "fontCharacter": "\\E060", + "fontCharacter": "\\E063", "fontColor": "#e37933" }, + "_pddl_light": { + "fontCharacter": "\\E064", + "fontColor": "#9068b0" + }, + "_pddl": { + "fontCharacter": "\\E064", + "fontColor": "#a074c4" + }, "_pdf_light": { - "fontCharacter": "\\E061", + "fontCharacter": "\\E065", "fontColor": "#b8383d" }, "_pdf": { - "fontCharacter": "\\E061", + "fontCharacter": "\\E065", "fontColor": "#cc3e44" }, "_perl_light": { - "fontCharacter": "\\E062", + "fontCharacter": "\\E066", "fontColor": "#498ba7" }, "_perl": { - "fontCharacter": "\\E062", + "fontCharacter": "\\E066", "fontColor": "#519aba" }, "_photoshop_light": { - "fontCharacter": "\\E063", + "fontCharacter": "\\E067", "fontColor": "#498ba7" }, "_photoshop": { - "fontCharacter": "\\E063", + "fontCharacter": "\\E067", "fontColor": "#519aba" }, "_php_light": { - "fontCharacter": "\\E064", + "fontCharacter": "\\E068", "fontColor": "#9068b0" }, "_php": { - "fontCharacter": "\\E064", + "fontCharacter": "\\E068", "fontColor": "#a074c4" }, + "_plan_light": { + "fontCharacter": "\\E069", + "fontColor": "#7fae42" + }, + "_plan": { + "fontCharacter": "\\E069", + "fontColor": "#8dc149" + }, + "_platformio_light": { + "fontCharacter": "\\E06A", + "fontColor": "#cc6d2e" + }, + "_platformio": { + "fontCharacter": "\\E06A", + "fontColor": "#e37933" + }, "_powershell_light": { - "fontCharacter": "\\E065", + "fontCharacter": "\\E06B", "fontColor": "#498ba7" }, "_powershell": { - "fontCharacter": "\\E065", + "fontCharacter": "\\E06B", "fontColor": "#519aba" }, "_pug_light": { - "fontCharacter": "\\E067", + "fontCharacter": "\\E06D", "fontColor": "#b8383d" }, "_pug": { - "fontCharacter": "\\E067", + "fontCharacter": "\\E06D", "fontColor": "#cc3e44" }, "_puppet_light": { - "fontCharacter": "\\E068", + "fontCharacter": "\\E06E", "fontColor": "#b7b73b" }, "_puppet": { - "fontCharacter": "\\E068", + "fontCharacter": "\\E06E", "fontColor": "#cbcb41" }, "_python_light": { - "fontCharacter": "\\E069", + "fontCharacter": "\\E06F", "fontColor": "#498ba7" }, "_python": { - "fontCharacter": "\\E069", + "fontCharacter": "\\E06F", "fontColor": "#519aba" }, "_react_light": { - "fontCharacter": "\\E06B", + "fontCharacter": "\\E071", "fontColor": "#498ba7" }, "_react": { - "fontCharacter": "\\E06B", + "fontCharacter": "\\E071", "fontColor": "#519aba" }, + "_react_1_light": { + "fontCharacter": "\\E071", + "fontColor": "#cc6d2e" + }, + "_react_1": { + "fontCharacter": "\\E071", + "fontColor": "#e37933" + }, + "_react_2_light": { + "fontCharacter": "\\E071", + "fontColor": "#b7b73b" + }, + "_react_2": { + "fontCharacter": "\\E071", + "fontColor": "#cbcb41" + }, + "_reasonml_light": { + "fontCharacter": "\\E072", + "fontColor": "#b8383d" + }, + "_reasonml": { + "fontCharacter": "\\E072", + "fontColor": "#cc3e44" + }, "_rollup_light": { - "fontCharacter": "\\E06C", + "fontCharacter": "\\E073", "fontColor": "#b8383d" }, "_rollup": { - "fontCharacter": "\\E06C", + "fontCharacter": "\\E073", "fontColor": "#cc3e44" }, "_ruby_light": { - "fontCharacter": "\\E06D", + "fontCharacter": "\\E074", "fontColor": "#b8383d" }, "_ruby": { - "fontCharacter": "\\E06D", + "fontCharacter": "\\E074", "fontColor": "#cc3e44" }, "_rust_light": { - "fontCharacter": "\\E06E", + "fontCharacter": "\\E075", "fontColor": "#627379" }, "_rust": { - "fontCharacter": "\\E06E", + "fontCharacter": "\\E075", "fontColor": "#6d8086" }, "_salesforce_light": { - "fontCharacter": "\\E06F", + "fontCharacter": "\\E076", "fontColor": "#498ba7" }, "_salesforce": { - "fontCharacter": "\\E06F", + "fontCharacter": "\\E076", "fontColor": "#519aba" }, "_sass_light": { - "fontCharacter": "\\E070", + "fontCharacter": "\\E077", "fontColor": "#dd4b78" }, "_sass": { - "fontCharacter": "\\E070", + "fontCharacter": "\\E077", "fontColor": "#f55385" }, "_sbt_light": { - "fontCharacter": "\\E071", + "fontCharacter": "\\E078", "fontColor": "#498ba7" }, "_sbt": { - "fontCharacter": "\\E071", + "fontCharacter": "\\E078", "fontColor": "#519aba" }, "_scala_light": { - "fontCharacter": "\\E072", + "fontCharacter": "\\E079", "fontColor": "#b8383d" }, "_scala": { - "fontCharacter": "\\E072", + "fontCharacter": "\\E079", "fontColor": "#cc3e44" }, "_shell_light": { - "fontCharacter": "\\E075", + "fontCharacter": "\\E07C", "fontColor": "#455155" }, "_shell": { - "fontCharacter": "\\E075", + "fontCharacter": "\\E07C", "fontColor": "#4d5a5e" }, "_slim_light": { - "fontCharacter": "\\E076", + "fontCharacter": "\\E07D", "fontColor": "#cc6d2e" }, "_slim": { - "fontCharacter": "\\E076", + "fontCharacter": "\\E07D", "fontColor": "#e37933" }, "_smarty_light": { - "fontCharacter": "\\E077", + "fontCharacter": "\\E07E", "fontColor": "#b7b73b" }, "_smarty": { - "fontCharacter": "\\E077", + "fontCharacter": "\\E07E", "fontColor": "#cbcb41" }, "_spring_light": { - "fontCharacter": "\\E078", + "fontCharacter": "\\E07F", "fontColor": "#7fae42" }, "_spring": { - "fontCharacter": "\\E078", + "fontCharacter": "\\E07F", "fontColor": "#8dc149" }, "_stylelint_light": { - "fontCharacter": "\\E079", + "fontCharacter": "\\E080", "fontColor": "#bfc2c1" }, "_stylelint": { - "fontCharacter": "\\E079", + "fontCharacter": "\\E080", "fontColor": "#d4d7d6" }, "_stylelint_1_light": { - "fontCharacter": "\\E079", + "fontCharacter": "\\E080", "fontColor": "#455155" }, "_stylelint_1": { - "fontCharacter": "\\E079", + "fontCharacter": "\\E080", "fontColor": "#4d5a5e" }, "_stylus_light": { - "fontCharacter": "\\E07A", + "fontCharacter": "\\E081", "fontColor": "#7fae42" }, "_stylus": { - "fontCharacter": "\\E07A", + "fontCharacter": "\\E081", "fontColor": "#8dc149" }, "_sublime_light": { - "fontCharacter": "\\E07B", + "fontCharacter": "\\E082", "fontColor": "#cc6d2e" }, "_sublime": { - "fontCharacter": "\\E07B", + "fontCharacter": "\\E082", "fontColor": "#e37933" }, "_svg_light": { - "fontCharacter": "\\E07C", + "fontCharacter": "\\E083", "fontColor": "#9068b0" }, "_svg": { - "fontCharacter": "\\E07C", + "fontCharacter": "\\E083", "fontColor": "#a074c4" }, "_svg_1_light": { - "fontCharacter": "\\E07C", + "fontCharacter": "\\E083", "fontColor": "#498ba7" }, "_svg_1": { - "fontCharacter": "\\E07C", + "fontCharacter": "\\E083", "fontColor": "#519aba" }, "_swift_light": { - "fontCharacter": "\\E07D", + "fontCharacter": "\\E084", "fontColor": "#cc6d2e" }, "_swift": { - "fontCharacter": "\\E07D", + "fontCharacter": "\\E084", "fontColor": "#e37933" }, "_terraform_light": { - "fontCharacter": "\\E07E", + "fontCharacter": "\\E085", "fontColor": "#9068b0" }, "_terraform": { - "fontCharacter": "\\E07E", + "fontCharacter": "\\E085", "fontColor": "#a074c4" }, "_tex_light": { - "fontCharacter": "\\E07F", + "fontCharacter": "\\E086", "fontColor": "#498ba7" }, "_tex": { - "fontCharacter": "\\E07F", + "fontCharacter": "\\E086", "fontColor": "#519aba" }, "_tex_1_light": { - "fontCharacter": "\\E07F", + "fontCharacter": "\\E086", "fontColor": "#b7b73b" }, "_tex_1": { - "fontCharacter": "\\E07F", + "fontCharacter": "\\E086", "fontColor": "#cbcb41" }, "_tex_2_light": { - "fontCharacter": "\\E07F", + "fontCharacter": "\\E086", "fontColor": "#cc6d2e" }, "_tex_2": { - "fontCharacter": "\\E07F", + "fontCharacter": "\\E086", "fontColor": "#e37933" }, "_tex_3_light": { - "fontCharacter": "\\E07F", + "fontCharacter": "\\E086", "fontColor": "#bfc2c1" }, "_tex_3": { - "fontCharacter": "\\E07F", + "fontCharacter": "\\E086", "fontColor": "#d4d7d6" }, "_todo": { - "fontCharacter": "\\E081" + "fontCharacter": "\\E088" + }, + "_tsconfig_light": { + "fontCharacter": "\\E089", + "fontColor": "#498ba7" + }, + "_tsconfig": { + "fontCharacter": "\\E089", + "fontColor": "#519aba" }, "_twig_light": { - "fontCharacter": "\\E082", + "fontCharacter": "\\E08A", "fontColor": "#7fae42" }, "_twig": { - "fontCharacter": "\\E082", + "fontCharacter": "\\E08A", "fontColor": "#8dc149" }, "_typescript_light": { - "fontCharacter": "\\E083", + "fontCharacter": "\\E08B", "fontColor": "#498ba7" }, "_typescript": { - "fontCharacter": "\\E083", + "fontCharacter": "\\E08B", "fontColor": "#519aba" }, "_typescript_1_light": { - "fontCharacter": "\\E083", + "fontCharacter": "\\E08B", "fontColor": "#b7b73b" }, "_typescript_1": { - "fontCharacter": "\\E083", + "fontCharacter": "\\E08B", "fontColor": "#cbcb41" }, "_vala_light": { - "fontCharacter": "\\E084", + "fontCharacter": "\\E08C", "fontColor": "#627379" }, "_vala": { - "fontCharacter": "\\E084", + "fontCharacter": "\\E08C", "fontColor": "#6d8086" }, "_video_light": { - "fontCharacter": "\\E085", + "fontCharacter": "\\E08D", "fontColor": "#dd4b78" }, "_video": { - "fontCharacter": "\\E085", + "fontCharacter": "\\E08D", "fontColor": "#f55385" }, "_vue_light": { - "fontCharacter": "\\E086", + "fontCharacter": "\\E08E", "fontColor": "#7fae42" }, "_vue": { - "fontCharacter": "\\E086", + "fontCharacter": "\\E08E", "fontColor": "#8dc149" }, "_wasm_light": { - "fontCharacter": "\\E087", + "fontCharacter": "\\E08F", "fontColor": "#9068b0" }, "_wasm": { - "fontCharacter": "\\E087", + "fontCharacter": "\\E08F", "fontColor": "#a074c4" }, "_wat_light": { - "fontCharacter": "\\E088", + "fontCharacter": "\\E090", "fontColor": "#9068b0" }, "_wat": { - "fontCharacter": "\\E088", + "fontCharacter": "\\E090", "fontColor": "#a074c4" }, "_webpack_light": { - "fontCharacter": "\\E089", + "fontCharacter": "\\E091", "fontColor": "#498ba7" }, "_webpack": { - "fontCharacter": "\\E089", + "fontCharacter": "\\E091", "fontColor": "#519aba" }, "_wgt_light": { - "fontCharacter": "\\E08A", + "fontCharacter": "\\E092", "fontColor": "#498ba7" }, "_wgt": { - "fontCharacter": "\\E08A", + "fontCharacter": "\\E092", "fontColor": "#519aba" }, "_windows_light": { - "fontCharacter": "\\E08B", + "fontCharacter": "\\E093", "fontColor": "#498ba7" }, "_windows": { - "fontCharacter": "\\E08B", + "fontCharacter": "\\E093", "fontColor": "#519aba" }, "_word_light": { - "fontCharacter": "\\E08C", + "fontCharacter": "\\E094", "fontColor": "#498ba7" }, "_word": { - "fontCharacter": "\\E08C", + "fontCharacter": "\\E094", "fontColor": "#519aba" }, "_xls_light": { - "fontCharacter": "\\E08D", + "fontCharacter": "\\E095", "fontColor": "#7fae42" }, "_xls": { - "fontCharacter": "\\E08D", + "fontCharacter": "\\E095", "fontColor": "#8dc149" }, "_xml_light": { - "fontCharacter": "\\E08E", + "fontCharacter": "\\E096", "fontColor": "#cc6d2e" }, "_xml": { - "fontCharacter": "\\E08E", + "fontCharacter": "\\E096", "fontColor": "#e37933" }, "_yarn_light": { - "fontCharacter": "\\E08F", + "fontCharacter": "\\E097", "fontColor": "#498ba7" }, "_yarn": { - "fontCharacter": "\\E08F", + "fontCharacter": "\\E097", "fontColor": "#519aba" }, "_yml_light": { - "fontCharacter": "\\E090", + "fontCharacter": "\\E098", "fontColor": "#9068b0" }, "_yml": { - "fontCharacter": "\\E090", + "fontCharacter": "\\E098", "fontColor": "#a074c4" }, "_zip_light": { - "fontCharacter": "\\E091", + "fontCharacter": "\\E099", "fontColor": "#b8383d" }, "_zip": { - "fontCharacter": "\\E091", + "fontCharacter": "\\E099", "fontColor": "#cc3e44" }, "_zip_1_light": { - "fontCharacter": "\\E091", + "fontCharacter": "\\E099", "fontColor": "#627379" }, "_zip_1": { - "fontCharacter": "\\E091", + "fontCharacter": "\\E099", "fontColor": "#6d8086" } }, @@ -1249,6 +1361,10 @@ "asm": "_asm", "s": "_asm", "h": "_c_1", + "aspx": "_html", + "ascx": "_html_1", + "asax": "_html_2", + "master": "_html_2", "hh": "_cpp_1", "hpp": "_cpp_1", "hxx": "_cpp_1", @@ -1286,6 +1402,8 @@ "article": "_go", "gradle": "_gradle", "gsp": "_grails", + "gql": "_graphql", + "graphql": "_graphql", "haml": "_haml", "hs": "_haskell", "lhs": "_haskell", @@ -1297,6 +1415,7 @@ "classpath": "_java", "js.map": "_javascript", "spec.js": "_javascript_1", + "test.js": "_javascript_1", "es": "_javascript", "es5": "_javascript", "es7": "_javascript", @@ -1305,6 +1424,7 @@ "jl": "_julia", "kt": "_kotlin", "kts": "_kotlin", + "dart": "_dart", "liquid": "_liquid", "ls": "_livescript", "argdown": "_argdown", @@ -1326,10 +1446,18 @@ "cmxa": "_ocaml", "odata": "_odata", "php.inc": "_php", + "pddl": "_pddl", + "plan": "_plan", + "happenings": "_happenings", "pug": "_pug", "pp": "_puppet", "epp": "_puppet", + "spec.jsx": "_react_1", + "test.jsx": "_react_1", "cjsx": "_react", + "spec.tsx": "_react_2", + "test.tsx": "_react_2", + "re": "_reasonml", "r": "_R", "erb": "_html_erb", "erb.html": "_html_erb", @@ -1352,6 +1480,7 @@ "toml": "_config", "twig": "_twig", "spec.ts": "_typescript_1", + "test.ts": "_typescript_1", "vala": "_vala", "vapi": "_vala", "vue": "_vue", @@ -1452,6 +1581,7 @@ "gulpfile": "_gulp", "ionic.config.json": "_ionic", "ionic.project": "_ionic", + "platformio.ini": "_platformio", "rollup.config.js": "_rollup", "sass-lint.yml": "_sass", "stylelint.config.js": "_stylelint", @@ -1459,6 +1589,9 @@ "yarn.lock": "_yarn", "webpack.config.js": "_webpack", "webpack.config.build.js": "_webpack", + "webpack.common.js": "_webpack", + "webpack.dev.js": "_webpack", + "webpack.prod.js": "_webpack", "license": "_license", "licence": "_license", "copying": "_license", @@ -1475,6 +1608,7 @@ "bat": "_windows", "clojure": "_clojure", "coffeescript": "_coffee", + "jsonc": "_json", "c": "_c", "cpp": "_cpp", "csharp": "_c-sharp", @@ -1484,7 +1618,7 @@ "go": "_go2", "groovy": "_grails", "handlebars": "_mustache", - "html": "_html", + "html": "_html_3", "properties": "_java", "java": "_java", "javascriptreact": "_react", @@ -1495,12 +1629,14 @@ "makefile": "_makefile", "markdown": "_markdown", "objective-c": "_c_2", + "objective-cpp": "_cpp_2", "perl": "_perl", "php": "_php", "powershell": "_powershell", "jade": "_jade", "python": "_python", "r": "_R", + "razor": "_html", "ruby": "_ruby", "rust": "_rust", "scss": "_sass", @@ -1539,6 +1675,10 @@ "asm": "_asm_light", "s": "_asm_light", "h": "_c_1_light", + "aspx": "_html_light", + "ascx": "_html_1_light", + "asax": "_html_2_light", + "master": "_html_2_light", "hh": "_cpp_1_light", "hpp": "_cpp_1_light", "hxx": "_cpp_1_light", @@ -1576,6 +1716,8 @@ "article": "_go_light", "gradle": "_gradle_light", "gsp": "_grails_light", + "gql": "_graphql_light", + "graphql": "_graphql_light", "haml": "_haml_light", "hs": "_haskell_light", "lhs": "_haskell_light", @@ -1587,6 +1729,7 @@ "classpath": "_java_light", "js.map": "_javascript_light", "spec.js": "_javascript_1_light", + "test.js": "_javascript_1_light", "es": "_javascript_light", "es5": "_javascript_light", "es7": "_javascript_light", @@ -1595,6 +1738,7 @@ "jl": "_julia_light", "kt": "_kotlin_light", "kts": "_kotlin_light", + "dart": "_dart_light", "liquid": "_liquid_light", "ls": "_livescript_light", "argdown": "_argdown_light", @@ -1616,10 +1760,18 @@ "cmxa": "_ocaml_light", "odata": "_odata_light", "php.inc": "_php_light", + "pddl": "_pddl_light", + "plan": "_plan_light", + "happenings": "_happenings_light", "pug": "_pug_light", "pp": "_puppet_light", "epp": "_puppet_light", + "spec.jsx": "_react_1_light", + "test.jsx": "_react_1_light", "cjsx": "_react_light", + "spec.tsx": "_react_2_light", + "test.tsx": "_react_2_light", + "re": "_reasonml_light", "r": "_R_light", "erb": "_html_erb_light", "erb.html": "_html_erb_light", @@ -1642,6 +1794,7 @@ "toml": "_config_light", "twig": "_twig_light", "spec.ts": "_typescript_1_light", + "test.ts": "_typescript_1_light", "vala": "_vala_light", "vapi": "_vala_light", "vue": "_vue_light", @@ -1718,6 +1871,7 @@ "bat": "_windows_light", "clojure": "_clojure_light", "coffeescript": "_coffee_light", + "jsonc": "_json_light", "c": "_c_light", "cpp": "_cpp_light", "csharp": "_c-sharp_light", @@ -1727,7 +1881,7 @@ "go": "_go2_light", "groovy": "_grails_light", "handlebars": "_mustache_light", - "html": "_html_light", + "html": "_html_3_light", "properties": "_java_light", "java": "_java_light", "javascriptreact": "_react_light", @@ -1738,12 +1892,14 @@ "makefile": "_makefile_light", "markdown": "_markdown_light", "objective-c": "_c_2_light", + "objective-cpp": "_cpp_2_light", "perl": "_perl_light", "php": "_php_light", "powershell": "_powershell_light", "jade": "_jade_light", "python": "_python_light", "r": "_R_light", + "razor": "_html_light", "ruby": "_ruby_light", "rust": "_rust_light", "scss": "_sass_light", @@ -1801,6 +1957,7 @@ "gulpfile": "_gulp_light", "ionic.config.json": "_ionic_light", "ionic.project": "_ionic_light", + "platformio.ini": "_platformio_light", "rollup.config.js": "_rollup_light", "sass-lint.yml": "_sass_light", "stylelint.config.js": "_stylelint_light", @@ -1808,6 +1965,9 @@ "yarn.lock": "_yarn_light", "webpack.config.js": "_webpack_light", "webpack.config.build.js": "_webpack_light", + "webpack.common.js": "_webpack_light", + "webpack.dev.js": "_webpack_light", + "webpack.prod.js": "_webpack_light", "license": "_license_light", "licence": "_license_light", "copying": "_license_light", @@ -1820,5 +1980,5 @@ "npm-debug.log": "_npm_ignored_light" } }, - "version": "https://github.com/jesseweed/seti-ui/commit/89175d7f9e0c70cd325b80a18a3c77fc8eb7c798" -} \ No newline at end of file + "version": "https://github.com/jesseweed/seti-ui/commit/904c16acced1134a81b31d71d60293288c31334b" +} diff --git a/extensions/theme-seti/package.json b/extensions/theme-seti/package.json index 554119b52b8..a9721611a6f 100644 --- a/extensions/theme-seti/package.json +++ b/extensions/theme-seti/package.json @@ -5,6 +5,7 @@ "displayName": "%displayName%", "description": "%description%", "publisher": "vscode", + "license": "MIT", "icon": "icons/seti-circular-128x128.png", "scripts": { "update": "node ./build/update-icon-theme.js" diff --git a/extensions/theme-solarized-dark/package.json b/extensions/theme-solarized-dark/package.json index bb43708ca1a..427b50fe482 100644 --- a/extensions/theme-solarized-dark/package.json +++ b/extensions/theme-solarized-dark/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "contributes": { "themes": [ diff --git a/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json b/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json index 30cbe306f4d..f2ee483bea4 100644 --- a/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json +++ b/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json @@ -72,7 +72,9 @@ "name": "Class name", "scope": [ "entity.name.class", - "entity.name.type" + "entity.name.type", + "entity.name.namespace", + "entity.name.scope-resolution" ], "settings": { "fontStyle": "", @@ -448,6 +450,7 @@ "statusBar.background": "#00212B", "statusBar.debuggingBackground": "#00212B", "statusBar.noFolderBackground": "#00212B", + "statusBarItem.remoteBackground": "#2AA19899", "statusBarItem.prominentBackground": "#003847", "statusBarItem.prominentHoverBackground": "#003847", // "statusBarItem.activeBackground": "", diff --git a/extensions/theme-solarized-light/package.json b/extensions/theme-solarized-light/package.json index 1925afaa394..3afb2b7ed9d 100644 --- a/extensions/theme-solarized-light/package.json +++ b/extensions/theme-solarized-light/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "contributes": { "themes": [ diff --git a/extensions/theme-solarized-light/themes/solarized-light-color-theme.json b/extensions/theme-solarized-light/themes/solarized-light-color-theme.json index 79caab20000..8cc7e74a779 100644 --- a/extensions/theme-solarized-light/themes/solarized-light-color-theme.json +++ b/extensions/theme-solarized-light/themes/solarized-light-color-theme.json @@ -72,7 +72,9 @@ "name": "Class name", "scope": [ "entity.name.class", - "entity.name.type" + "entity.name.type", + "entity.name.namespace", + "entity.name.scope-resolution" ], "settings": { "foreground": "#268BD2" @@ -219,16 +221,14 @@ "meta.diff.header" ], "settings": { - "background": "#b58900", "fontStyle": "italic", - "foreground": "#E0EDDD" + "foreground": "#268bd2" } }, { "name": "diff: deleted", "scope": "markup.deleted", "settings": { - "background": "#eee8d5", "fontStyle": "", "foreground": "#dc322f" } @@ -237,7 +237,6 @@ "name": "diff: changed", "scope": "markup.changed", "settings": { - "background": "#eee8d5", "fontStyle": "", "foreground": "#cb4b16" } @@ -246,7 +245,6 @@ "name": "diff: inserted", "scope": "markup.inserted", "settings": { - "background": "#eee8d5", "foreground": "#219186" } }, @@ -417,7 +415,7 @@ "tab.activeBackground": "#FDF6E3", "tab.inactiveForeground": "#586E75", "tab.inactiveBackground": "#D3CBB7", - "tab.modifiedBorder": "#cb4b16", + "tab.activeModifiedBorder": "#cb4b16", // "tab.activeBackground": "", // "tab.activeForeground": "", // "tab.inactiveForeground": "", @@ -447,6 +445,7 @@ "statusBar.debuggingBackground": "#EEE8D5", "statusBar.noFolderBackground": "#EEE8D5", // "statusBar.foreground": "", + "statusBarItem.remoteBackground": "#AC9D57", "statusBarItem.prominentBackground": "#DDD6C1", "statusBarItem.prominentHoverBackground": "#DDD6C199", // "statusBarItem.activeBackground": "", diff --git a/extensions/theme-tomorrow-night-blue/package.json b/extensions/theme-tomorrow-night-blue/package.json index bed66ce548a..1266ac58ca4 100644 --- a/extensions/theme-tomorrow-night-blue/package.json +++ b/extensions/theme-tomorrow-night-blue/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "contributes": { "themes": [ diff --git a/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json b/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json index 8d01980349f..6c985d1ea5e 100644 --- a/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json +++ b/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json @@ -30,6 +30,7 @@ "debugToolBar.background": "#001c40", "titleBar.activeBackground": "#001126", "statusBar.background": "#001126", + "statusBarItem.remoteBackground": "#0e639c", "statusBar.noFolderBackground": "#001126", "statusBar.debuggingBackground": "#001126", "activityBar.background": "#001733", @@ -100,7 +101,7 @@ }, { "name": "Class, Support", - "scope": "entity.name.class, entity.name.type, support.type, support.class", + "scope": "entity.name.class, entity.name.type, entity.name.namespace, entity.name.scope-resolution, support.type, support.class", "settings": { "fontStyle": "", "foreground": "#FFEEAD" diff --git a/extensions/typescript-basics/build/update-grammars.js b/extensions/typescript-basics/build/update-grammars.js index 2f069183879..527fa2c1d43 100644 --- a/extensions/typescript-basics/build/update-grammars.js +++ b/extensions/typescript-basics/build/update-grammars.js @@ -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. *--------------------------------------------------------------------------------------------*/ +// @ts-check 'use strict'; var updateGrammar = require('../../../build/npm/update-grammar'); @@ -16,12 +17,26 @@ function removeDom(grammar) { return grammar; } +function patchJsdoctype(grammar) { + grammar.repository['jsdoctype'].patterns = grammar.repository['jsdoctype'].patterns.filter(pattern => { + if (pattern.name && pattern.name.indexOf('illegal') >= -1) { + return false; + } + return true; + }); + return grammar; +} + +function patchGrammar(grammar) { + return removeDom(patchJsdoctype(grammar)); +} + function adaptToJavaScript(grammar, replacementScope) { grammar.name = 'JavaScript (with React support)'; - grammar.fileTypes = ['.js', '.jsx', '.es6', '.mjs' ]; + grammar.fileTypes = ['.js', '.jsx', '.es6', '.mjs']; grammar.scopeName = `source${replacementScope}`; - var fixScopeNames = function(rule) { + var fixScopeNames = function (rule) { if (typeof rule.name === 'string') { rule.name = rule.name.replace(/\.tsx/g, replacementScope); } @@ -43,12 +58,7 @@ function adaptToJavaScript(grammar, replacementScope) { } var tsGrammarRepo = 'Microsoft/TypeScript-TmLanguage'; -updateGrammar.update(tsGrammarRepo, 'TypeScript.tmLanguage', './syntaxes/TypeScript.tmLanguage.json', grammar => removeDom(grammar)); -updateGrammar.update(tsGrammarRepo, 'TypeScriptReact.tmLanguage', './syntaxes/TypeScriptReact.tmLanguage.json', grammar => removeDom(grammar)); -updateGrammar.update(tsGrammarRepo, 'TypeScriptReact.tmLanguage', '../javascript/syntaxes/JavaScript.tmLanguage.json', grammar => adaptToJavaScript(removeDom(grammar), '.js')); -updateGrammar.update(tsGrammarRepo, 'TypeScriptReact.tmLanguage', '../javascript/syntaxes/JavaScriptReact.tmLanguage.json', grammar => adaptToJavaScript(removeDom(grammar), '.js.jsx')); - - - - - +updateGrammar.update(tsGrammarRepo, 'TypeScript.tmLanguage', './syntaxes/TypeScript.tmLanguage.json', grammar => patchGrammar(grammar)); +updateGrammar.update(tsGrammarRepo, 'TypeScriptReact.tmLanguage', './syntaxes/TypeScriptReact.tmLanguage.json', grammar => patchGrammar(grammar)); +updateGrammar.update(tsGrammarRepo, 'TypeScriptReact.tmLanguage', '../javascript/syntaxes/JavaScript.tmLanguage.json', grammar => adaptToJavaScript(patchGrammar(grammar), '.js')); +updateGrammar.update(tsGrammarRepo, 'TypeScriptReact.tmLanguage', '../javascript/syntaxes/JavaScriptReact.tmLanguage.json', grammar => adaptToJavaScript(patchGrammar(grammar), '.js.jsx')); diff --git a/extensions/typescript-basics/cgmanifest.json b/extensions/typescript-basics/cgmanifest.json index 9be4a04ca8f..077f5f0424e 100644 --- a/extensions/typescript-basics/cgmanifest.json +++ b/extensions/typescript-basics/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "TypeScript-TmLanguage", "repositoryUrl": "https://github.com/Microsoft/TypeScript-TmLanguage", - "commitHash": "f17fefd8d6bbf181ea27be2faccb2a274366e6db" + "commitHash": "84238ef0fa1c7e4e2c9fe77875d832dab9f57e5d" } }, "license": "MIT", diff --git a/extensions/typescript-basics/package.json b/extensions/typescript-basics/package.json index 3f697de5ced..185a8a2bc71 100644 --- a/extensions/typescript-basics/package.json +++ b/extensions/typescript-basics/package.json @@ -79,18 +79,8 @@ } }, { - "scopeName": "documentation.markdown.injection", - "path": "./syntaxes/MarkdownDocumentationInjection.tmLanguage.json", - "injectTo": [ - "source.ts", - "source.tsx", - "source.js", - "source.js.jsx" - ] - }, - { - "scopeName": "documentation.example.injection", - "path": "./syntaxes/ExampleJsDoc.injection.tmLanguage.json", + "scopeName": "documentation.injection", + "path": "./syntaxes/jsdoc.injection.tmLanguage.json", "injectTo": [ "source.ts", "source.tsx", @@ -140,4 +130,4 @@ } ] } -} \ No newline at end of file +} diff --git a/extensions/typescript-basics/syntaxes/MarkdownDocumentationInjection.tmLanguage.json b/extensions/typescript-basics/syntaxes/MarkdownDocumentationInjection.tmLanguage.json deleted file mode 100644 index d7711577168..00000000000 --- a/extensions/typescript-basics/syntaxes/MarkdownDocumentationInjection.tmLanguage.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "injectionSelector": "L:comment.block.documentation", - "patterns": [ - { - "include": "#markdown-comment" - } - ], - "repository": { - "markdown-comment": { - "begin": "(?<=/\\*\\*)\\s*$", - "while": "(^|\\G)\\s*\\*(?!/)(?=([^*]|[*](?!/))*$)", - "patterns": [ - { - "include": "text.html.markdown#fenced_code_block" - }, - { - "include": "text.html.markdown#lists" - }, - { - "include": "source.ts#docblock" - }, - { - "include": "text.html.markdown#inline" - } - ] - } - }, - "scopeName": "documentation.markdown.injection" -} \ No newline at end of file diff --git a/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json b/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json index d5279579325..3d1b37da01e 100644 --- a/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json +++ b/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/f17fefd8d6bbf181ea27be2faccb2a274366e6db", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/84238ef0fa1c7e4e2c9fe77875d832dab9f57e5d", "name": "TypeScript", "scopeName": "source.ts", "patterns": [ @@ -132,6 +132,9 @@ "name": "keyword.control.switch.ts", "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.ts entity.name.function.ts" @@ -429,7 +432,7 @@ "name": "keyword.operator.definiteassignment.ts" } }, - "end": "(?=$|^|[;,=}]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[;,=}]|((?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.ts variable.other.constant.ts entity.name.function.ts" } }, - "end": "(?=$|^|[;,=}]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[;,=}]|((?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.ts" @@ -950,7 +965,7 @@ "include": "#comment" }, { - "begin": "(?x)(?=((\\b(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "meta.definition.property.ts entity.name.function.ts" @@ -1120,7 +1141,7 @@ "name": "keyword.operator.assignment.ts" } }, - "end": "(?=$|^|[,);}\\]]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[,);}\\]]|((?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.ts" @@ -1294,7 +1315,7 @@ }, { "name": "meta.method.declaration.ts", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.ts" @@ -1326,7 +1347,7 @@ }, "object-literal-method-declaration": { "name": "meta.method.declaration.ts", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -1347,7 +1368,7 @@ "include": "#function-body" }, { - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -1369,7 +1390,7 @@ ] }, "method-declaration-name": { - "begin": "(?x)(?=((\\b(? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -1560,7 +1581,7 @@ "include": "#parameter-name" }, { - "include": "#type-annotation" + "include": "#parameter-type-annotation" }, { "include": "#variable-initializer" @@ -1597,9 +1618,12 @@ }, "class-expression": { "name": "meta.class.ts", - "begin": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*:(\\s*\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/)*\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.ts" @@ -2537,6 +2644,33 @@ } } }, + { + "name": "meta.object.member.ts", + "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)\\(\\s*([\\{\\[]\\s*)?$)", + "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*([\\{\\[]\\s*)?$)", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -2612,6 +2746,9 @@ } ] }, + { + "include": "#possibly-arrow-return-type" + }, { "include": "#expression" } @@ -2651,20 +2788,7 @@ "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()", "patterns": [ { - "include": "#literal" - }, - { - "include": "#support-objects" - }, - { - "include": "#object-identifiers" - }, - { - "include": "#punctuation-accessor" - }, - { - "name": "keyword.operator.expression.import.ts", - "match": "(?:(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*))?\\(\\s*[\\{\\[]\\s*$)", + "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*[\\{\\[]\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -2739,7 +2883,7 @@ ] }, { - "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*))?\\()|(<))\\s*$)", + "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -2809,7 +2953,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.ts" @@ -2887,6 +3031,21 @@ }, "cast": { "patterns": [ + { + "name": "cast.expr.ts", + "match": "\\s*(<)\\s*(const)\\s*(>)", + "captures": { + "1": { + "name": "meta.brace.angle.ts" + }, + "2": { + "name": "storage.modifier.ts" + }, + "3": { + "name": "meta.brace.angle.ts" + } + } + }, { "name": "cast.expr.ts", "begin": "(?:(?*?\\&\\|\\^]|[^_$[:alnum:]](?:\\+\\+|\\-\\-)|[^\\+]\\+|[^\\-]\\-))\\s*(<)(?!]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", "captures": { "1": { "name": "punctuation.accessor.ts" @@ -3423,7 +3607,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.ts" @@ -3544,6 +3728,25 @@ } ] }, + "parameter-type-annotation": { + "patterns": [ + { + "name": "meta.type.annotation.ts", + "begin": "(:)", + "beginCaptures": { + "1": { + "name": "keyword.operator.type.annotation.ts" + } + }, + "end": "(?=[,)])|(?==[^>])", + "patterns": [ + { + "include": "#type" + } + ] + } + ] + }, "return-type": { "patterns": [ { @@ -3616,7 +3819,7 @@ ] }, "possibly-arrow-return-type": { - "begin": "(?<=\\)|^)\\s*(:)(?=\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*=>)", + "begin": "(?<=\\)|^)\\s*(:)(?=\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*=>)", "beginCaptures": { "1": { "name": "meta.arrow.ts meta.return.type.arrow.ts keyword.operator.type.annotation.ts" @@ -3762,6 +3965,14 @@ { "include": "#type-function-return-type" }, + { + "match": "(?)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))))", + "match": "(?x)(?:(?)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))))", "captures": { "1": { "name": "storage.modifier.ts" @@ -4270,6 +4481,29 @@ }, "template": { "patterns": [ + { + "name": "string.template.ts", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "end": "(?=`)", + "patterns": [ + { + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", + "end": "(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "patterns": [ + { + "include": "#support-function-call-identifiers" + }, + { + "name": "entity.name.function.tagged-template.ts", + "match": "([_$[:alpha:]][_$[:alnum:]]*)" + } + ] + }, + { + "include": "#type-arguments" + } + ] + }, { "name": "string.template.ts", "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", @@ -4338,7 +4572,7 @@ "patterns": [ { "name": "string.regexp.ts", - "begin": "(?|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))", + "begin": "(?|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.ts" @@ -4361,7 +4595,7 @@ }, { "name": "string.regexp.ts", - "begin": "(?\\s*$)", + "begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`)))+\\s*/>\\s*$)", "beginCaptures": { "1": { "name": "punctuation.definition.comment.ts" @@ -5090,10 +5324,6 @@ }, "jsdoctype": { "patterns": [ - { - "name": "invalid.illegal.type.jsdoc", - "match": "\\G{(?:[^}*]|\\*[^/}])+$" - }, { "contentName": "entity.name.type.instance.jsdoc", "begin": "\\G({)", diff --git a/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json b/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json index 07ebe8ea1b0..d50da9102c9 100644 --- a/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json +++ b/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/f17fefd8d6bbf181ea27be2faccb2a274366e6db", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/84238ef0fa1c7e4e2c9fe77875d832dab9f57e5d", "name": "TypeScriptReact", "scopeName": "source.tsx", "patterns": [ @@ -132,6 +132,9 @@ "name": "keyword.control.switch.tsx", "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\!)?(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.tsx entity.name.function.tsx" @@ -432,7 +435,7 @@ "name": "keyword.operator.definiteassignment.tsx" } }, - "end": "(?=$|^|[;,=}]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[;,=}]|((?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.tsx variable.other.constant.tsx entity.name.function.tsx" } }, - "end": "(?=$|^|[;,=}]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[;,=}]|((?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.tsx" @@ -953,7 +968,7 @@ "include": "#comment" }, { - "begin": "(?x)(?=((\\b(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?:(\\?)|(\\!))?(?=\\s*\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "meta.definition.property.tsx entity.name.function.tsx" @@ -1123,7 +1144,7 @@ "name": "keyword.operator.assignment.tsx" } }, - "end": "(?=$|^|[,);}\\]]|(\\s+(of|in)\\s+))", + "end": "(?=$|^|[,);}\\]]|((?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.tsx" @@ -1297,7 +1318,7 @@ }, { "name": "meta.method.declaration.tsx", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.tsx" @@ -1329,7 +1350,7 @@ }, "object-literal-method-declaration": { "name": "meta.method.declaration.tsx", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -1350,7 +1371,7 @@ "include": "#function-body" }, { - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -1372,7 +1393,7 @@ ] }, "method-declaration-name": { - "begin": "(?x)(?=((\\b(? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -1563,7 +1584,7 @@ "include": "#parameter-name" }, { - "include": "#type-annotation" + "include": "#parameter-type-annotation" }, { "include": "#variable-initializer" @@ -1600,9 +1621,12 @@ }, "class-expression": { "name": "meta.class.tsx", - "begin": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*:(\\s*\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/)*\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.tsx" @@ -2540,6 +2647,33 @@ } } }, + { + "name": "meta.object.member.tsx", + "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)\\(\\s*([\\{\\[]\\s*)?$)", + "begin": "(?<=:)\\s*(async)?(?=\\s*(<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*([\\{\\[]\\s*)?$)", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -2615,6 +2749,9 @@ } ] }, + { + "include": "#possibly-arrow-return-type" + }, { "include": "#expression" } @@ -2654,20 +2791,7 @@ "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()", "patterns": [ { - "include": "#literal" - }, - { - "include": "#support-objects" - }, - { - "include": "#object-identifiers" - }, - { - "include": "#punctuation-accessor" - }, - { - "name": "keyword.operator.expression.import.tsx", - "match": "(?:(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*))?\\(\\s*[\\{\\[]\\s*$)", + "begin": "(?<=[(=,])\\s*(async)?(?=\\s*((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*[\\{\\[]\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -2742,7 +2886,7 @@ ] }, { - "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*))?\\()|(<))\\s*$)", + "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -2812,7 +2956,7 @@ } }, { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.tsx" @@ -2958,6 +3102,17 @@ "name": "keyword.operator.expression.void.tsx", "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", "captures": { "1": { "name": "punctuation.accessor.tsx" @@ -3389,7 +3558,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", + "match": "(?x)(?:(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.tsx" @@ -3510,6 +3679,25 @@ } ] }, + "parameter-type-annotation": { + "patterns": [ + { + "name": "meta.type.annotation.tsx", + "begin": "(:)", + "beginCaptures": { + "1": { + "name": "keyword.operator.type.annotation.tsx" + } + }, + "end": "(?=[,)])|(?==[^>])", + "patterns": [ + { + "include": "#type" + } + ] + } + ] + }, "return-type": { "patterns": [ { @@ -3582,7 +3770,7 @@ ] }, "possibly-arrow-return-type": { - "begin": "(?<=\\)|^)\\s*(:)(?=\\s*([^<>\\(\\)\\{\\}]|\\<[^<>]+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*=>)", + "begin": "(?<=\\)|^)\\s*(:)(?=\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*=>)", "beginCaptures": { "1": { "name": "meta.arrow.tsx meta.return.type.arrow.tsx keyword.operator.type.annotation.tsx" @@ -3728,6 +3916,14 @@ { "include": "#type-function-return-type" }, + { + "match": "(?\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "end": "(?=`)", + "patterns": [ + { + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", + "end": "(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", + "patterns": [ + { + "include": "#support-function-call-identifiers" + }, + { + "name": "entity.name.function.tagged-template.tsx", + "match": "([_$[:alpha:]][_$[:alnum:]]*)" + } + ] + }, + { + "include": "#type-arguments" + } + ] + }, { "name": "string.template.tsx", "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", @@ -4304,7 +4523,7 @@ "patterns": [ { "name": "string.regexp.tsx", - "begin": "(?|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))", + "begin": "(?|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.tsx" @@ -4327,7 +4546,7 @@ }, { "name": "string.regexp.tsx", - "begin": "(?\\s*$)", + "begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`)))+\\s*/>\\s*$)", "beginCaptures": { "1": { "name": "punctuation.definition.comment.tsx" @@ -5056,10 +5275,6 @@ }, "jsdoctype": { "patterns": [ - { - "name": "invalid.illegal.type.jsdoc", - "match": "\\G{(?:[^}*]|\\*[^/}])+$" - }, { "contentName": "entity.name.type.instance.jsdoc", "begin": "\\G({)", @@ -5099,7 +5314,7 @@ ] }, "jsx-tag-without-attributes-in-expression": { - "begin": "(?:*]|&&|\\|\\||\\?|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*(?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", + "begin": "(?:*]|&&|\\|\\||\\?|\\*\\/|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*(?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "end": "(?!(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "patterns": [ { @@ -5159,7 +5374,7 @@ ] }, "jsx-tag-in-expression": { - "begin": "(?x)\n (?:*]|&&|\\|\\||\\?|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", + "begin": "(?x)\n (?:*]|&&|\\|\\||\\?|\\*\\/|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^yield|[^\\._$[:alnum:]]yield|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "end": "(?!(<)\\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))", "patterns": [ { diff --git a/extensions/typescript-basics/syntaxes/ExampleJsDoc.injection.tmLanguage.json b/extensions/typescript-basics/syntaxes/jsdoc.injection.tmLanguage.json similarity index 51% rename from extensions/typescript-basics/syntaxes/ExampleJsDoc.injection.tmLanguage.json rename to extensions/typescript-basics/syntaxes/jsdoc.injection.tmLanguage.json index 03c52cb97ff..b7b4db2d2a5 100644 --- a/extensions/typescript-basics/syntaxes/ExampleJsDoc.injection.tmLanguage.json +++ b/extensions/typescript-basics/syntaxes/jsdoc.injection.tmLanguage.json @@ -2,10 +2,31 @@ "injectionSelector": "L:comment.block.documentation", "patterns": [ { - "include": "#example" + "include": "#jsdocbody" } ], "repository": { + "jsdocbody": { + "begin": "(?<=/\\*\\*)([^*]|\\*(?!/))*$", + "while": "(^|\\G)\\s*\\*(?!/)(?=([^*]|[*](?!/))*$)", + "patterns": [ + { + "include": "text.html.markdown#fenced_code_block" + }, + { + "include": "text.html.markdown#lists" + }, + { + "include": "#example" + }, + { + "include": "source.ts#docblock" + }, + { + "include": "text.html.markdown#inline" + } + ] + }, "example": { "begin": "((@)example)\\s+(?=([^*]|[*](?!/))*$).*$", "while": "(^|\\G)\\s(?!@)(?=([^*]|[*](?!/))*$)", @@ -25,5 +46,5 @@ ] } }, - "scopeName": "documentation.example.injection" + "scopeName": "documentation.injection" } \ No newline at end of file diff --git a/extensions/typescript-basics/test/colorize-fixtures/test-jsdoc-example.ts b/extensions/typescript-basics/test/colorize-fixtures/test-jsdoc-example.ts new file mode 100644 index 00000000000..411f9bbede3 --- /dev/null +++ b/extensions/typescript-basics/test/colorize-fixtures/test-jsdoc-example.ts @@ -0,0 +1,8 @@ +/** + * @example + * 1 + 1 + * + * @other + * not colored + */ +const a = 1 \ No newline at end of file diff --git a/extensions/typescript-basics/test/colorize-fixtures/test-jsdoc-markdown.ts b/extensions/typescript-basics/test/colorize-fixtures/test-jsdoc-markdown.ts new file mode 100644 index 00000000000..136f8b1bafb --- /dev/null +++ b/extensions/typescript-basics/test/colorize-fixtures/test-jsdoc-markdown.ts @@ -0,0 +1,7 @@ +/** + * **Bold** + * ```js + * 1 + code + * ``` + */ +const a = 1 \ No newline at end of file diff --git a/extensions/typescript-basics/test/colorize-fixtures/test-jsdoc-multiline-type.ts b/extensions/typescript-basics/test/colorize-fixtures/test-jsdoc-multiline-type.ts new file mode 100644 index 00000000000..eda831efe02 --- /dev/null +++ b/extensions/typescript-basics/test/colorize-fixtures/test-jsdoc-multiline-type.ts @@ -0,0 +1,22 @@ +/** + * @typedef {{ + * id: number, + * fn: !Function, + * context: (!Object|undefined) + * }} + * @private + */ +goog.dom.animationFrame.Task_; + + +/** + * @typedef {{ + * measureTask: goog.dom.animationFrame.Task_, + * mutateTask: goog.dom.animationFrame.Task_, + * state: (!Object|undefined), + * args: (!Array|undefined), + * isScheduled: boolean + * }} + * @private + */ +goog.dom.animationFrame.TaskSet_; \ No newline at end of file diff --git a/extensions/typescript-basics/test/colorize-results/test-jsdoc-example_ts.json b/extensions/typescript-basics/test/colorize-results/test-jsdoc-example_ts.json new file mode 100644 index 00000000000..ea15234c214 --- /dev/null +++ b/extensions/typescript-basics/test/colorize-results/test-jsdoc-example_ts.json @@ -0,0 +1,277 @@ +[ + { + "c": "/**", + "t": "source.ts comment.block.documentation.ts punctuation.definition.comment.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " * ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "@", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc punctuation.definition.block.tag.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "example", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts meta.embedded.block.example.source.ts", + "r": { + "dark_plus": "meta.embedded: #D4D4D4", + "light_plus": "meta.embedded: #000000", + "dark_vs": "meta.embedded: #D4D4D4", + "light_vs": "meta.embedded: #000000", + "hc_black": "meta.embedded: #FFFFFF" + } + }, + { + "c": "1", + "t": "source.ts comment.block.documentation.ts meta.embedded.block.example.source.ts constant.numeric.decimal.tsx", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts meta.embedded.block.example.source.ts", + "r": { + "dark_plus": "meta.embedded: #D4D4D4", + "light_plus": "meta.embedded: #000000", + "dark_vs": "meta.embedded: #D4D4D4", + "light_vs": "meta.embedded: #000000", + "hc_black": "meta.embedded: #FFFFFF" + } + }, + { + "c": "+", + "t": "source.ts comment.block.documentation.ts meta.embedded.block.example.source.ts keyword.operator.arithmetic.tsx", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts meta.embedded.block.example.source.ts", + "r": { + "dark_plus": "meta.embedded: #D4D4D4", + "light_plus": "meta.embedded: #000000", + "dark_vs": "meta.embedded: #D4D4D4", + "light_vs": "meta.embedded: #000000", + "hc_black": "meta.embedded: #FFFFFF" + } + }, + { + "c": "1", + "t": "source.ts comment.block.documentation.ts meta.embedded.block.example.source.ts constant.numeric.decimal.tsx", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " * ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "@", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc punctuation.definition.block.tag.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "other", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " * not colored", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "*/", + "t": "source.ts comment.block.documentation.ts punctuation.definition.comment.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "const", + "t": "source.ts meta.var.expr.ts storage.type.ts", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ", + "t": "source.ts meta.var.expr.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "a", + "t": "source.ts meta.var.expr.ts meta.var-single-variable.expr.ts meta.definition.variable.ts variable.other.constant.ts", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": " ", + "t": "source.ts meta.var.expr.ts meta.var-single-variable.expr.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.ts meta.var.expr.ts keyword.operator.assignment.ts", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.ts meta.var.expr.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "1", + "t": "source.ts meta.var.expr.ts constant.numeric.decimal.ts", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + } +] \ No newline at end of file diff --git a/extensions/typescript-basics/test/colorize-results/test-jsdoc-markdown_ts.json b/extensions/typescript-basics/test/colorize-results/test-jsdoc-markdown_ts.json new file mode 100644 index 00000000000..eea45a645eb --- /dev/null +++ b/extensions/typescript-basics/test/colorize-results/test-jsdoc-markdown_ts.json @@ -0,0 +1,310 @@ +[ + { + "c": "/**", + "t": "source.ts comment.block.documentation.ts punctuation.definition.comment.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " * ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "**", + "t": "source.ts comment.block.documentation.ts markup.bold.markdown punctuation.definition.bold.markdown", + "r": { + "dark_plus": "markup.bold: #569CD6", + "light_plus": "markup.bold: #000080", + "dark_vs": "markup.bold: #569CD6", + "light_vs": "markup.bold: #000080", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "Bold", + "t": "source.ts comment.block.documentation.ts markup.bold.markdown", + "r": { + "dark_plus": "markup.bold: #569CD6", + "light_plus": "markup.bold: #000080", + "dark_vs": "markup.bold: #569CD6", + "light_vs": "markup.bold: #000080", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "**", + "t": "source.ts comment.block.documentation.ts markup.bold.markdown punctuation.definition.bold.markdown", + "r": { + "dark_plus": "markup.bold: #569CD6", + "light_plus": "markup.bold: #000080", + "dark_vs": "markup.bold: #569CD6", + "light_vs": "markup.bold: #000080", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts markup.fenced_code.block.markdown", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "```", + "t": "source.ts comment.block.documentation.ts markup.fenced_code.block.markdown punctuation.definition.markdown", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "js", + "t": "source.ts comment.block.documentation.ts markup.fenced_code.block.markdown", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts markup.fenced_code.block.markdown meta.embedded.block.javascript", + "r": { + "dark_plus": "meta.embedded: #D4D4D4", + "light_plus": "meta.embedded: #000000", + "dark_vs": "meta.embedded: #D4D4D4", + "light_vs": "meta.embedded: #000000", + "hc_black": "meta.embedded: #FFFFFF" + } + }, + { + "c": "1", + "t": "source.ts comment.block.documentation.ts markup.fenced_code.block.markdown meta.embedded.block.javascript constant.numeric.decimal.js", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts markup.fenced_code.block.markdown meta.embedded.block.javascript", + "r": { + "dark_plus": "meta.embedded: #D4D4D4", + "light_plus": "meta.embedded: #000000", + "dark_vs": "meta.embedded: #D4D4D4", + "light_vs": "meta.embedded: #000000", + "hc_black": "meta.embedded: #FFFFFF" + } + }, + { + "c": "+", + "t": "source.ts comment.block.documentation.ts markup.fenced_code.block.markdown meta.embedded.block.javascript keyword.operator.arithmetic.js", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts markup.fenced_code.block.markdown meta.embedded.block.javascript", + "r": { + "dark_plus": "meta.embedded: #D4D4D4", + "light_plus": "meta.embedded: #000000", + "dark_vs": "meta.embedded: #D4D4D4", + "light_vs": "meta.embedded: #000000", + "hc_black": "meta.embedded: #FFFFFF" + } + }, + { + "c": "code", + "t": "source.ts comment.block.documentation.ts markup.fenced_code.block.markdown meta.embedded.block.javascript variable.other.readwrite.js", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "meta.embedded: #D4D4D4", + "light_vs": "meta.embedded: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts markup.fenced_code.block.markdown", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "```", + "t": "source.ts comment.block.documentation.ts markup.fenced_code.block.markdown punctuation.definition.markdown", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "*/", + "t": "source.ts comment.block.documentation.ts punctuation.definition.comment.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "const", + "t": "source.ts meta.var.expr.ts storage.type.ts", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ", + "t": "source.ts meta.var.expr.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "a", + "t": "source.ts meta.var.expr.ts meta.var-single-variable.expr.ts meta.definition.variable.ts variable.other.constant.ts", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": " ", + "t": "source.ts meta.var.expr.ts meta.var-single-variable.expr.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "=", + "t": "source.ts meta.var.expr.ts keyword.operator.assignment.ts", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.ts meta.var.expr.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "1", + "t": "source.ts meta.var.expr.ts constant.numeric.decimal.ts", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #09885A", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #09885A", + "hc_black": "constant.numeric: #B5CEA8" + } + } +] \ No newline at end of file diff --git a/extensions/typescript-basics/test/colorize-results/test-jsdoc-multiline-type_ts.json b/extensions/typescript-basics/test/colorize-results/test-jsdoc-multiline-type_ts.json new file mode 100644 index 00000000000..cc1eba5f197 --- /dev/null +++ b/extensions/typescript-basics/test/colorize-results/test-jsdoc-multiline-type_ts.json @@ -0,0 +1,684 @@ +[ + { + "c": "/**", + "t": "source.ts comment.block.documentation.ts punctuation.definition.comment.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " * ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "@", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc punctuation.definition.block.tag.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "typedef", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "{", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc punctuation.definition.bracket.curly.begin.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": "{", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " id: number,", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " fn: !Function,", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " context: (!Object|undefined)", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " }", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": "}", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc punctuation.definition.bracket.curly.end.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " * ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "@", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc punctuation.definition.block.tag.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "private", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "*/", + "t": "source.ts comment.block.documentation.ts punctuation.definition.comment.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "goog", + "t": "source.ts variable.other.object.ts", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.ts punctuation.accessor.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "dom", + "t": "source.ts variable.other.object.property.ts", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.ts punctuation.accessor.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "animationFrame", + "t": "source.ts variable.other.object.property.ts", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.ts punctuation.accessor.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "Task_", + "t": "source.ts variable.other.property.ts", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ";", + "t": "source.ts punctuation.terminator.statement.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "/**", + "t": "source.ts comment.block.documentation.ts punctuation.definition.comment.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " * ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "@", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc punctuation.definition.block.tag.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "typedef", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "{", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc punctuation.definition.bracket.curly.begin.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": "{", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " measureTask: goog.dom.animationFrame.Task_,", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " mutateTask: goog.dom.animationFrame.Task_,", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " state: (!Object|undefined),", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " args: (!Array|undefined),", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " isScheduled: boolean", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " *", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": " }", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": "}", + "t": "source.ts comment.block.documentation.ts entity.name.type.instance.jsdoc punctuation.definition.bracket.curly.end.jsdoc", + "r": { + "dark_plus": "entity.name.type: #4EC9B0", + "light_plus": "entity.name.type: #267F99", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "entity.name.type: #4EC9B0" + } + }, + { + "c": " * ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "@", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc punctuation.definition.block.tag.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": "private", + "t": "source.ts comment.block.documentation.ts storage.type.class.jsdoc", + "r": { + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": " ", + "t": "source.ts comment.block.documentation.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "*/", + "t": "source.ts comment.block.documentation.ts punctuation.definition.comment.ts", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668" + } + }, + { + "c": "goog", + "t": "source.ts variable.other.object.ts", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.ts punctuation.accessor.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "dom", + "t": "source.ts variable.other.object.property.ts", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.ts punctuation.accessor.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "animationFrame", + "t": "source.ts variable.other.object.property.ts", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ".", + "t": "source.ts punctuation.accessor.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "TaskSet_", + "t": "source.ts variable.other.property.ts", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": ";", + "t": "source.ts punctuation.terminator.statement.ts", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + } +] \ No newline at end of file diff --git a/extensions/typescript-language-features/README.md b/extensions/typescript-language-features/README.md index 26942f9d460..b3a5a072e35 100644 --- a/extensions/typescript-language-features/README.md +++ b/extensions/typescript-language-features/README.md @@ -1,7 +1,7 @@ -# Language Features for Typescript and Javascript files +# Language Features for TypeScript and JavaScript files **Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled. ## Features -See [Typescript in Visual Studio Code](https://code.visualstudio.com/docs/languages/typescript) and [Javascript in Visual Studio Code](https://code.visualstudio.com/docs/languages/javascript) to learn about the features of this extension. \ No newline at end of file +See [TypeScript in Visual Studio Code](https://code.visualstudio.com/docs/languages/typescript) and [JavaScript in Visual Studio Code](https://code.visualstudio.com/docs/languages/javascript) to learn about the features of this extension. diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 0cea8d8ec7c..fc003585c9b 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -17,13 +17,15 @@ ], "dependencies": { "jsonc-parser": "^2.0.1", + "rimraf": "^2.6.3", "semver": "5.5.1", - "vscode-extension-telemetry": "0.1.0", + "vscode-extension-telemetry": "0.1.1", "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "8.0.33", + "@types/node": "^10.14.8", "@types/semver": "^5.5.0", + "@types/rimraf": "2.0.2", "vscode": "^1.1.10" }, "scripts": { @@ -83,7 +85,7 @@ ], "default": null, "description": "%typescript.npm%", - "scope": "application" + "scope": "machine" }, "typescript.check.npmIsInstalled": { "type": "boolean", @@ -129,7 +131,7 @@ }, "default": [], "description": "%typescript.tsserver.pluginPaths%", - "scope": "application" + "scope": "machine" }, "typescript.tsserver.trace": { "type": "string", @@ -358,12 +360,6 @@ "description": "%format.placeOpenBraceOnNewLineForControlBlocks%", "scope": "resource" }, - "jsDocCompletion.enabled": { - "type": "boolean", - "default": true, - "description": "%jsDocCompletion.enabled%", - "scope": "resource" - }, "javascript.implicitProjectConfig.checkJs": { "type": "boolean", "default": false, @@ -424,6 +420,18 @@ "description": "%configuration.suggest.autoImports%", "scope": "resource" }, + "javascript.suggest.completeJSDocs": { + "type": "boolean", + "default": true, + "description": "%configuration.suggest.completeJSDocs%", + "scope": "resource" + }, + "typescript.suggest.completeJSDocs": { + "type": "boolean", + "default": true, + "description": "%configuration.suggest.completeJSDocs%", + "scope": "resource" + }, "typescript.locale": { "type": [ "string", @@ -512,6 +520,18 @@ "description": "%typescript.preferences.importModuleSpecifier%", "scope": "resource" }, + "javascript.preferences.renameShorthandProperties": { + "type": "boolean", + "default": true, + "description": "%typescript.preferences.renameShorthandProperties%", + "scope": "resource" + }, + "typescript.preferences.renameShorthandProperties": { + "type": "boolean", + "default": true, + "description": "%typescript.preferences.renameShorthandProperties%", + "scope": "resource" + }, "typescript.updateImportsOnFileMove.enabled": { "type": "string", "enum": [ @@ -571,6 +591,12 @@ "default": true, "description": "%configuration.surveys.enabled%", "scope": "window" + }, + "typescript.tsserver.useSeparateSyntaxServer": { + "type": "boolean", + "default": true, + "description": "%configuration.tsserver.useSeparateSyntaxServer%", + "scope": "window" } } }, @@ -687,7 +713,7 @@ "problemPatterns": [ { "name": "tsc", - "regexp": "^([^\\s].*)[\\(:](\\d+)[,:](\\d+)(?:\\):\\s+|\\s+-\\s+)(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$", + "regexp": "^([^\\s].*)[\\(:](\\d+)[,:](\\d+)(?:\\):\\s+|\\s+-\\s+)(error|warning|info)\\s+TS(\\d+)\\s*:\\s*(.*)$", "file": 1, "line": 2, "column": 3, diff --git a/extensions/typescript-language-features/package.nls.json b/extensions/typescript-language-features/package.nls.json index 2cd347a012a..a83acf9c6f2 100644 --- a/extensions/typescript-language-features/package.nls.json +++ b/extensions/typescript-language-features/package.nls.json @@ -33,11 +33,10 @@ "javascript.referencesCodeLens.enabled": "Enable/disable references CodeLens in JavaScript files.", "typescript.referencesCodeLens.enabled": "Enable/disable references CodeLens in TypeScript files.", "typescript.implementationsCodeLens.enabled": "Enable/disable implementations CodeLens. This CodeLens shows the implementers of an interface.", - "typescript.openTsServerLog.title": "Open TS Server log.", - "typescript.restartTsServer": "Restart TS server.", - "typescript.selectTypeScriptVersion.title": "Select TypeScript Version.", + "typescript.openTsServerLog.title": "Open TS Server log", + "typescript.restartTsServer": "Restart TS server", + "typescript.selectTypeScriptVersion.title": "Select TypeScript Version...", "typescript.reportStyleChecksAsWarnings": "Report style checks as warnings.", - "jsDocCompletion.enabled": "Enable/disable auto JSDoc comments.", "javascript.implicitProjectConfig.checkJs": "Enable/disable semantic checking of JavaScript files. Existing jsconfig.json or tsconfig.json files override this setting. Requires using TypeScript 2.3.1 or newer in the workspace.", "typescript.npm": "Specifies the path to the NPM executable used for Automatic Type Acquisition. Requires using TypeScript 2.3.4 or newer in the workspace.", "typescript.check.npmIsInstalled": "Check if NPM is installed for Automatic Type Acquisition.", @@ -50,6 +49,7 @@ "typescript.problemMatchers.tsc.label": "TypeScript problems", "typescript.problemMatchers.tscWatch.label": "TypeScript problems (watch mode)", "configuration.suggest.paths": "Enable/disable suggestions for paths in import statements and require calls.", + "configuration.tsserver.useSeparateSyntaxServer": "Enable/disable spawning a separate TypeScript server that can more quickly respond to syntax related operations, such as calculating folding or computing document symbols. Requires using TypeScript 3.4.0 or newer in the workspace.", "typescript.locale": "Sets the locale used to report JavaScript and TypeScript errors. Requires using TypeScript 2.6.0 or newer in the workspace. Default of `null` uses VS Code's locale.", "javascript.implicitProjectConfig.experimentalDecorators": "Enable/disable `experimentalDecorators` for JavaScript files that are not part of a project. Existing jsconfig.json or tsconfig.json files override this setting. Requires using TypeScript 2.3.1 or newer in the workspace.", "configuration.suggest.autoImports": "Enable/disable auto import suggestions. Requires using TypeScript 2.6.1 or newer in the workspace.", @@ -58,7 +58,7 @@ "typescript.suggestionActions.enabled": "Enable/disable suggestion diagnostics for TypeScript files in the editor. Requires using TypeScript 2.8 or newer in the workspace.", "typescript.preferences.quoteStyle": "Preferred quote style to use for quick fixes: `single` quotes, `double` quotes, or `auto` infer quote type from existing imports. Requires using TypeScript 2.9 or newer in the workspace.", "typescript.preferences.importModuleSpecifier": "Preferred path style for auto imports.", - "typescript.preferences.importModuleSpecifier.auto": "Infer the shortest path type.", + "typescript.preferences.importModuleSpecifier.auto": "Automatically select import path style. Prefers using a relative import if `baseUrl` is configured and the relative path has fewer segments than the non-relative import.", "typescript.preferences.importModuleSpecifier.relative": "Relative to the file location.", "typescript.preferences.importModuleSpecifier.nonRelative": "Based on the `baseUrl` configured in your `jsconfig.json` / `tsconfig.json`.", "typescript.updateImportsOnFileMove.enabled": "Enable/disable automatic updating of import paths when you rename or move a file in VS Code. Requires using TypeScript 2.9 or newer in the workspace.", @@ -67,5 +67,7 @@ "typescript.updateImportsOnFileMove.enabled.never": "Never rename paths and don't prompt.", "typescript.autoClosingTags": "Enable/disable automatic closing of JSX tags. Requires using TypeScript 3.0 or newer in the workspace.", "typescript.suggest.enabled": "Enabled/disable autocomplete suggestions.", - "configuration.surveys.enabled": "Enabled/disable occasional surveys that help us improve VS Code's JavaScript and TypeScript support." + "configuration.surveys.enabled": "Enabled/disable occasional surveys that help us improve VS Code's JavaScript and TypeScript support.", + "configuration.suggest.completeJSDocs": "Enable/disable suggestion to complete JSDoc comments.", + "typescript.preferences.renameShorthandProperties": "Enable/disable introducing aliases for object shorthand properties during renames. Requires using TypeScript 3.4 or newer in the workspace." } \ No newline at end of file diff --git a/extensions/typescript-language-features/src/commands/goToProjectConfiguration.ts b/extensions/typescript-language-features/src/commands/goToProjectConfiguration.ts index 61729eafa8b..9273683ba4c 100644 --- a/extensions/typescript-language-features/src/commands/goToProjectConfiguration.ts +++ b/extensions/typescript-language-features/src/commands/goToProjectConfiguration.ts @@ -10,6 +10,7 @@ import { nulToken } from '../utils/cancellation'; import { Command } from '../utils/commandManager'; import { Lazy } from '../utils/lazy'; import { isImplicitProjectConfigFile, openOrCreateConfigFile } from '../utils/tsconfig'; +import { ServerResponse } from '../typescriptService'; const localize = nls.loadMessageBundle(); @@ -68,13 +69,13 @@ async function goToProjectConfig( return; } - let res: protocol.ProjectInfoResponse | undefined; + let res: ServerResponse.Response | undefined; try { res = await client.execute('projectInfo', { file, needFileNameList: false }, nulToken); } catch { // noop } - if (!res || !res.body) { + if (!res || res.type !== 'response' || !res.body) { vscode.window.showWarningMessage(localize('typescript.projectConfigCouldNotGetInfo', 'Could not determine TypeScript or JavaScript project')); return; } diff --git a/extensions/typescript-language-features/src/extension.ts b/extensions/typescript-language-features/src/extension.ts index 782aa98106d..ffa61f231f1 100644 --- a/extensions/typescript-language-features/src/extension.ts +++ b/extensions/typescript-language-features/src/extension.ts @@ -7,9 +7,10 @@ import * as vscode from 'vscode'; import { Api, getExtensionApi } from './api'; import { registerCommands } from './commands/index'; import { LanguageConfigurationManager } from './features/languageConfiguration'; -import TypeScriptTaskProviderManager from './features/task'; import TypeScriptServiceClientHost from './typeScriptServiceClientHost'; import { flatten } from './utils/arrays'; +import * as electron from './utils/electron'; +import * as rimraf from 'rimraf'; import { CommandManager } from './utils/commandManager'; import * as fileSchemes from './utils/fileSchemes'; import { standardLanguageDescriptions } from './utils/languageDescription'; @@ -19,6 +20,7 @@ import ManagedFileContextManager from './utils/managedFileContext'; import { PluginManager } from './utils/plugins'; import * as ProjectStatus from './utils/projectStatus'; import { Surveyor } from './utils/surveyor'; +import TscTaskProvider from './features/task'; export function activate( context: vscode.ExtensionContext @@ -37,7 +39,7 @@ export function activate( }); registerCommands(commandManager, lazyClientHost, pluginManager); - context.subscriptions.push(new TypeScriptTaskProviderManager(lazyClientHost.map(x => x.serviceClient))); + context.subscriptions.push(vscode.workspace.registerTaskProvider('typescript', new TscTaskProvider(lazyClientHost.map(x => x.serviceClient)))); context.subscriptions.push(new LanguageConfigurationManager()); import('./features/tsconfig').then(module => { @@ -128,4 +130,8 @@ function isSupportedDocument( return false; } return fileSchemes.isSupportedScheme(document.uri.scheme); -} \ No newline at end of file +} + +export function deactivate() { + rimraf.sync(electron.getInstanceDir()); +} diff --git a/extensions/typescript-language-features/src/features/bufferSyncSupport.ts b/extensions/typescript-language-features/src/features/bufferSyncSupport.ts index 4cf76147d16..f662cb21af6 100644 --- a/extensions/typescript-language-features/src/features/bufferSyncSupport.ts +++ b/extensions/typescript-language-features/src/features/bufferSyncSupport.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as fs from 'fs'; import * as vscode from 'vscode'; import * as Proto from '../protocol'; import { ITypeScriptServiceClient } from '../typescriptService'; @@ -14,11 +13,17 @@ import * as languageModeIds from '../utils/languageModeIds'; import { ResourceMap } from '../utils/resourceMap'; import * as typeConverters from '../utils/typeConverters'; -enum BufferKind { +const enum BufferKind { TypeScript = 1, JavaScript = 2, } +const enum BufferState { + Initial = 1, + Open = 2, + Closed = 2, +} + function mode2ScriptKind(mode: string): 'TS' | 'TSX' | 'JS' | 'JSX' | undefined { switch (mode) { case languageModeIds.typescript: return 'TS'; @@ -29,12 +34,141 @@ function mode2ScriptKind(mode: string): 'TS' | 'TSX' | 'JS' | 'JSX' | undefined return undefined; } +class CloseOperation { + readonly type = 'close'; + constructor( + public readonly args: string + ) { } +} + +class OpenOperation { + readonly type = 'open'; + constructor( + public readonly args: Proto.OpenRequestArgs + ) { } +} + +class ChangeOperation { + readonly type = 'change'; + constructor( + public readonly args: Proto.FileCodeEdits + ) { } +} + +/** + * Manages synchronization of buffers with the TS server. + * + * If supported, batches together file changes. This allows the TS server to more efficiently process changes. + */ +class BufferSynchronizer { + + private readonly _pending = new Map(); + + constructor( + private readonly client: ITypeScriptServiceClient + ) { } + + public open(args: Proto.OpenRequestArgs) { + if (this.supportsBatching) { + this.updatePending(args.file, pending => { + pending.set(args.file, new OpenOperation(args)); + }); + } else { + this.client.executeWithoutWaitingForResponse('open', args); + } + } + + public close(filepath: string) { + if (this.supportsBatching) { + this.updatePending(filepath, pending => { + pending.set(filepath, new CloseOperation(filepath)); + }); + } else { + const args: Proto.FileRequestArgs = { file: filepath }; + this.client.executeWithoutWaitingForResponse('close', args); + } + } + + public change(filepath: string, events: readonly vscode.TextDocumentContentChangeEvent[]) { + if (!events.length) { + return; + } + + if (this.supportsBatching) { + this.updatePending(filepath, pending => { + pending.set(filepath, new ChangeOperation({ + fileName: filepath, + textChanges: events.map((change): Proto.CodeEdit => ({ + newText: change.text, + start: typeConverters.Position.toLocation(change.range.start), + end: typeConverters.Position.toLocation(change.range.end), + })).reverse(), // Send the edits end-of-document to start-of-document order + })); + }); + } else { + for (const { range, text } of events) { + const args: Proto.ChangeRequestArgs = { + insertString: text, + ...typeConverters.Range.toFormattingRequestArgs(filepath, range) + }; + this.client.executeWithoutWaitingForResponse('change', args); + } + } + } + + public beforeCommand(command: string) { + if (command === 'updateOpen') { + return; + } + + this.flush(); + } + + private flush() { + if (!this.supportsBatching) { + // We've already eagerly synchronized + this._pending.clear(); + return; + } + + if (this._pending.size > 0) { + const closedFiles: string[] = []; + const openFiles: Proto.OpenRequestArgs[] = []; + const changedFiles: Proto.FileCodeEdits[] = []; + for (const change of this._pending.values()) { + switch (change.type) { + case 'change': changedFiles.push(change.args); break; + case 'open': openFiles.push(change.args); break; + case 'close': closedFiles.push(change.args); break; + } + } + this.client.executeWithoutWaitingForResponse('updateOpen', { changedFiles, closedFiles, openFiles }); + this._pending.clear(); + } + } + + private get supportsBatching(): boolean { + return this.client.apiVersion.gte(API.v340) && vscode.workspace.getConfiguration('typescript', null).get('useBatchedBufferSync', true); + } + + private updatePending(filepath: string, f: (pending: Map) => void): void { + if (this._pending.has(filepath)) { + // we saw this file before, make sure we flush before working with it again + this.flush(); + } + f(this._pending); + } +} + class SyncedBuffer { + private state = BufferState.Initial; + constructor( private readonly document: vscode.TextDocument, public readonly filepath: string, - private readonly client: ITypeScriptServiceClient + private readonly client: ITypeScriptServiceClient, + private readonly synchronizer: BufferSynchronizer, ) { } public open(): void { @@ -63,7 +197,8 @@ class SyncedBuffer { } } - this.client.executeWithoutWaitingForResponse('open', args); + this.synchronizer.open(args); + this.state = BufferState.Open; } public get resource(): vscode.Uri { @@ -88,20 +223,16 @@ class SyncedBuffer { } public close(): void { - const args: Proto.FileRequestArgs = { - file: this.filepath - }; - this.client.executeWithoutWaitingForResponse('close', args); + this.synchronizer.close(this.filepath); + this.state = BufferState.Closed; } - public onContentChanged(events: vscode.TextDocumentContentChangeEvent[]): void { - for (const { range, text } of events) { - const args: Proto.ChangeRequestArgs = { - insertString: text, - ...typeConverters.Range.toFormattingRequestArgs(this.filepath, range) - }; - this.client.executeWithoutWaitingForResponse('change', args); + public onContentChanged(events: readonly vscode.TextDocumentContentChangeEvent[]): void { + if (this.state !== BufferState.Open) { + console.error(`Unexpected buffer state: ${this.state}`); } + + this.synchronizer.change(this.filepath, events); } } @@ -157,8 +288,7 @@ class GetErrRequest { }; client.executeAsync('geterr', args, _token.token) - .catch(() => true) - .then(() => { + .finally(() => { if (this._done) { return; } @@ -188,6 +318,7 @@ export default class BufferSyncSupport extends Disposable { private readonly diagnosticDelayer: Delayer; private pendingGetErr: GetErrRequest | undefined; private listening: boolean = false; + private readonly synchronizer: BufferSynchronizer; constructor( client: ITypeScriptServiceClient, @@ -202,6 +333,7 @@ export default class BufferSyncSupport extends Disposable { const pathNormalizer = (path: vscode.Uri) => this.client.normalizedPath(path); this.syncedBuffers = new SyncedBufferMap(pathNormalizer); this.pendingDiagnostics = new PendingDiagnostics(pathNormalizer); + this.synchronizer = new BufferSynchronizer(client); this.updateConfiguration(); vscode.workspace.onDidChangeConfiguration(this.updateConfiguration, this, this._disposables); @@ -253,7 +385,7 @@ export default class BufferSyncSupport extends Disposable { return; } - const syncedBuffer = new SyncedBuffer(document, filepath, this.client); + const syncedBuffer = new SyncedBuffer(document, filepath, this.client, this.synchronizer); this.syncedBuffers.set(resource, syncedBuffer); syncedBuffer.open(); this.requestDiagnostic(syncedBuffer); @@ -267,10 +399,8 @@ export default class BufferSyncSupport extends Disposable { this.pendingDiagnostics.delete(resource); this.syncedBuffers.delete(resource); syncedBuffer.close(); - if (!fs.existsSync(resource.fsPath)) { - this._onDelete.fire(resource); - this.requestAllDiagnostics(); - } + this._onDelete.fire(resource); + this.requestAllDiagnostics(); } public interuptGetErr(f: () => R): R { @@ -285,6 +415,10 @@ export default class BufferSyncSupport extends Disposable { return result; } + public beforeCommand(command: string): void { + this.synchronizer.beforeCommand(command); + } + private onDidCloseTextDocument(document: vscode.TextDocument): void { this.closeResource(document.uri); } @@ -353,20 +487,20 @@ export default class BufferSyncSupport extends Disposable { private sendPendingDiagnostics(): void { const orderedFileSet = this.pendingDiagnostics.getOrderedFileSet(); + if (this.pendingGetErr) { + this.pendingGetErr.cancel(); + + for (const file of this.pendingGetErr.files.entries) { + orderedFileSet.set(file.resource, undefined); + } + } + // Add all open TS buffers to the geterr request. They might be visible for (const buffer of this.syncedBuffers.values) { orderedFileSet.set(buffer.resource, undefined); } if (orderedFileSet.size) { - if (this.pendingGetErr) { - this.pendingGetErr.cancel(); - - for (const file of this.pendingGetErr.files.entries) { - orderedFileSet.set(file.resource, undefined); - } - } - const getErr = this.pendingGetErr = GetErrRequest.executeGetErrRequest(this.client, orderedFileSet, () => { if (this.pendingGetErr === getErr) { this.pendingGetErr = undefined; diff --git a/extensions/typescript-language-features/src/features/completions.ts b/extensions/typescript-language-features/src/features/completions.ts index 05102d4177c..fdfabd4365f 100644 --- a/extensions/typescript-language-features/src/features/completions.ts +++ b/extensions/typescript-language-features/src/features/completions.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import * as Proto from '../protocol'; import * as PConst from '../protocol.const'; -import { ITypeScriptServiceClient } from '../typescriptService'; +import { ITypeScriptServiceClient, ServerResponse } from '../typescriptService'; import API from '../utils/api'; import { nulToken } from '../utils/cancellation'; import { applyCodeAction } from '../utils/codeAction'; @@ -15,10 +15,11 @@ import { Command, CommandManager } from '../utils/commandManager'; import { ConfigurationDependentRegistration } from '../utils/dependentRegistration'; import { memoize } from '../utils/memoize'; import * as Previewer from '../utils/previewer'; +import { snippetForFunctionCall } from '../utils/snippetForFunctionCall'; +import TelemetryReporter from '../utils/telemetry'; import * as typeConverters from '../utils/typeConverters'; import TypingsStatus from '../utils/typingsStatus'; import FileConfigurationManager from './fileConfigurationManager'; -import { snippetForFunctionCall } from '../utils/snippetForFunctionCall'; const localize = nls.loadMessageBundle(); @@ -49,12 +50,7 @@ class MyCompletionItem extends vscode.CompletionItem { ) { super(tsEntry.name, MyCompletionItem.convertKind(tsEntry.kind)); - if (tsEntry.isRecommended) { - // Make sure isRecommended property always comes first - // https://github.com/Microsoft/vscode/issues/40325 - this.sortText = tsEntry.sortText; - this.preselect = true; - } else if (tsEntry.source) { + if (tsEntry.source) { // De-prioritze auto-imports // https://github.com/Microsoft/vscode/issues/40311 this.sortText = '\uffff' + tsEntry.sortText; @@ -62,6 +58,10 @@ class MyCompletionItem extends vscode.CompletionItem { this.sortText = tsEntry.sortText; } + if (tsEntry.isRecommended) { + this.preselect = true; + } + this.position = position; this.useCodeSnippet = useCodeSnippetsOnMethodSuggest && (this.kind === vscode.CompletionItemKind.Function || this.kind === vscode.CompletionItemKind.Method); @@ -74,7 +74,9 @@ class MyCompletionItem extends vscode.CompletionItem { } this.insertText = tsEntry.insertText; - this.filterText = tsEntry.insertText; + // Set filterText for intelliCode and bracket accessors , but not for `this.` completions since it results in + // them being overly prioritized. #74164 + this.filterText = tsEntry.insertText && !/^this\./.test(tsEntry.insertText) ? tsEntry.insertText : undefined; if (completionContext.isMemberCompletion && completionContext.dotAccessorContext) { this.filterText = completionContext.dotAccessorContext.text + (this.insertText || this.label); @@ -86,7 +88,6 @@ class MyCompletionItem extends vscode.CompletionItem { if (tsEntry.kindModifiers) { const kindModifiers = new Set(tsEntry.kindModifiers.split(/\s+/g)); - if (kindModifiers.has(PConst.KindModifiers.optional)) { if (!this.insertText) { this.insertText = this.label; @@ -123,12 +124,14 @@ class MyCompletionItem extends vscode.CompletionItem { return; } - // Try getting longer, prefix based range for completions that span words + const wordRange = this.document.getWordRangeAtPosition(this.position); if (wordRange) { - this.range = wordRange; + // TODO: Reverted next line due to https://github.com/Microsoft/vscode/issues/66187 + // this.range = wordRange; } + // Try getting longer, prefix based range for completions that span words const text = line.slice(Math.max(0, this.position.character - this.label.length), this.position.character).toLowerCase(); const entryName = this.label.toLowerCase(); for (let i = entryName.length; i >= 0; --i) { @@ -202,7 +205,6 @@ class MyCompletionItem extends vscode.CompletionItem { case PConst.Kind.enum: case PConst.Kind.interface: commitCharacters.push('.', ';'); - break; case PConst.Kind.module: @@ -331,6 +333,7 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider private readonly typingsStatus: TypingsStatus, private readonly fileConfigurationManager: FileConfigurationManager, commandManager: CommandManager, + private readonly telemetryReporter: TelemetryReporter, onCompletionAccepted: (item: vscode.CompletionItem) => void ) { commandManager.register(new ApplyCompletionCodeActionCommand(this.client)); @@ -367,7 +370,7 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider return null; } - await this.client.interuptGetErr(() => this.fileConfigurationManager.ensureConfigurationForDocument(document, token)); + await this.client.interruptGetErr(() => this.fileConfigurationManager.ensureConfigurationForDocument(document, token)); const args: Proto.CompletionsRequestArgs = { ...typeConverters.Position.toFileLocationRequestArgs(file, position), @@ -383,7 +386,30 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider let entries: ReadonlyArray; let metadata: any | undefined; if (this.client.apiVersion.gte(API.v300)) { - const response = await this.client.interuptGetErr(() => this.client.execute('completionInfo', args, token)); + const startTime = Date.now(); + let response: ServerResponse.Response | undefined; + try { + response = await this.client.interruptGetErr(() => this.client.execute('completionInfo', args, token)); + } finally { + const duration: number = Date.now() - startTime; + + /* __GDPR__ + "completions.execute" : { + "duration" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, + "type" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, + "count" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, + "${include}": [ + "${TypeScriptCommonProperties}" + ] + } + */ + this.telemetryReporter.logTelemetry('completions.execute', { + duration: duration + '', + type: response ? response.type : 'unknown', + count: (response && response.type === 'response' && response.body ? response.body.entries.length : 0) + '' + }); + } + if (response.type !== 'response' || !response.body) { return null; } @@ -401,7 +427,7 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider entries = response.body.entries; metadata = response.metadata; } else { - const response = await this.client.interuptGetErr(() => this.client.execute('completions', args, token)); + const response = await this.client.interruptGetErr(() => this.client.execute('completions', args, token)); if (response.type !== 'response' || !response.body) { return null; } @@ -454,8 +480,8 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider ] }; - const response = await this.client.interuptGetErr(() => this.client.execute('completionEntryDetails', args, token)); - if (response.type !== 'response' || !response.body) { + const response = await this.client.interruptGetErr(() => this.client.execute('completionEntryDetails', args, token)); + if (response.type !== 'response' || !response.body || !response.body.length) { return item; } @@ -478,7 +504,7 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider item.additionalTextEdits = codeAction.additionalTextEdits; if (detail && item.useCodeSnippet) { - const shouldCompleteFunction = await this.isValidFunctionCompletionContext(filepath, item.position, token); + const shouldCompleteFunction = await this.isValidFunctionCompletionContext(filepath, item.position, item.document, token); if (shouldCompleteFunction) { const { snippet, parameterCount } = snippetForFunctionCall(item, detail.displayParts); item.insertText = snippet; @@ -628,30 +654,31 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider private async isValidFunctionCompletionContext( filepath: string, position: vscode.Position, + document: vscode.TextDocument, token: vscode.CancellationToken ): Promise { // Workaround for https://github.com/Microsoft/TypeScript/issues/12677 - // Don't complete function calls inside of destructive assigments or imports + // Don't complete function calls inside of destructive assignments or imports try { const args: Proto.FileLocationRequestArgs = typeConverters.Position.toFileLocationRequestArgs(filepath, position); const response = await this.client.execute('quickinfo', args, token); - if (response.type !== 'response') { - return true; + if (response.type === 'response' && response.body) { + switch (response.body.kind) { + case 'var': + case 'let': + case 'const': + case 'alias': + return false; + } } - - const { body } = response; - switch (body && body.kind) { - case 'var': - case 'let': - case 'const': - case 'alias': - return false; - default: - return true; - } - } catch (e) { - return true; + } catch { + // Noop } + + // Don't complete function call if there is already something that looks like a function call + // https://github.com/Microsoft/vscode/issues/18131 + const after = document.lineAt(position.line).text.slice(position.character); + return after.match(/^[a-z_$0-9]*\s*\(/gi) === null; } } @@ -674,10 +701,11 @@ export function register( typingsStatus: TypingsStatus, fileConfigurationManager: FileConfigurationManager, commandManager: CommandManager, + telemetryReporter: TelemetryReporter, onCompletionAccepted: (item: vscode.CompletionItem) => void ) { return new ConfigurationDependentRegistration(modeId, 'suggest.enabled', () => vscode.languages.registerCompletionItemProvider(selector, - new TypeScriptCompletionItemProvider(client, modeId, typingsStatus, fileConfigurationManager, commandManager, onCompletionAccepted), + new TypeScriptCompletionItemProvider(client, modeId, typingsStatus, fileConfigurationManager, commandManager, telemetryReporter, onCompletionAccepted), ...TypeScriptCompletionItemProvider.triggerCharacters)); } diff --git a/extensions/typescript-language-features/src/features/definitions.ts b/extensions/typescript-language-features/src/features/definitions.ts index 5fe72c2005f..fd3a1f10e79 100644 --- a/extensions/typescript-language-features/src/features/definitions.ts +++ b/extensions/typescript-language-features/src/features/definitions.ts @@ -37,10 +37,18 @@ export default class TypeScriptDefinitionProvider extends DefinitionProviderBase return response.body.definitions .map((location): vscode.DefinitionLink => { const target = typeConverters.Location.fromTextSpan(this.client.toResource(location.file), location); + if ((location as any).contextStart) { + return { + originSelectionRange: span, + targetRange: typeConverters.Range.fromLocations((location as any).contextStart, (location as any).contextEnd), + targetUri: target.uri, + targetSelectionRange: target.range, + }; + } return { originSelectionRange: span, targetRange: target.range, - targetUri: target.uri, + targetUri: target.uri }; }); } diff --git a/extensions/typescript-language-features/src/features/diagnostics.ts b/extensions/typescript-language-features/src/features/diagnostics.ts index 2e58cab4c5b..327573e8c18 100644 --- a/extensions/typescript-language-features/src/features/diagnostics.ts +++ b/extensions/typescript-language-features/src/features/diagnostics.ts @@ -5,7 +5,27 @@ import * as vscode from 'vscode'; import { ResourceMap } from '../utils/resourceMap'; -import { DiagnosticLanguage, allDiagnosticLangauges } from '../utils/languageDescription'; +import { DiagnosticLanguage } from '../utils/languageDescription'; +import * as arrays from '../utils/arrays'; +import { Disposable } from '../utils/dispose'; + +function diagnosticsEquals(a: vscode.Diagnostic, b: vscode.Diagnostic): boolean { + if (a === b) { + return true; + } + + return a.code === b.code + && a.message === b.message + && a.severity === b.severity + && a.source === b.source + && a.range.isEqual(b.range) + && arrays.equals(a.relatedInformation || arrays.empty, b.relatedInformation || arrays.empty, (a, b) => { + return a.message === b.message + && a.location.range.isEqual(b.location.range) + && a.location.uri.fsPath === b.location.uri.fsPath; + }) + && arrays.equals(a.tags || arrays.empty, b.tags || arrays.empty); +} export const enum DiagnosticKind { Syntax, @@ -14,7 +34,7 @@ export const enum DiagnosticKind { } class FileDiagnostics { - private readonly _diagnostics = new Map(); + private readonly _diagnostics = new Map>(); constructor( public readonly file: vscode.Uri, @@ -24,19 +44,17 @@ class FileDiagnostics { public updateDiagnostics( language: DiagnosticLanguage, kind: DiagnosticKind, - diagnostics: vscode.Diagnostic[] + diagnostics: ReadonlyArray ): boolean { if (language !== this.language) { this._diagnostics.clear(); this.language = language; } - if (diagnostics.length === 0) { - const existing = this._diagnostics.get(kind); - if (!existing || existing && existing.length === 0) { - // No need to update - return false; - } + const existing = this._diagnostics.get(kind); + if (arrays.equals(existing || arrays.empty, diagnostics, diagnosticsEquals)) { + // No need to update + return false; } this._diagnostics.set(kind, diagnostics); @@ -60,35 +78,34 @@ class FileDiagnostics { return this.get(DiagnosticKind.Suggestion).filter(x => { if (!enableSuggestions) { // Still show unused - return x.tags && x.tags.indexOf(vscode.DiagnosticTag.Unnecessary) !== -1; + return x.tags && x.tags.includes(vscode.DiagnosticTag.Unnecessary); } return true; }); } - private get(kind: DiagnosticKind): vscode.Diagnostic[] { + private get(kind: DiagnosticKind): ReadonlyArray { return this._diagnostics.get(kind) || []; } } -interface LangaugeDiagnosticSettings { +interface LanguageDiagnosticSettings { readonly validate: boolean; readonly enableSuggestions: boolean; } +function areLanguageDiagnosticSettingsEqual(currentSettings: LanguageDiagnosticSettings, newSettings: LanguageDiagnosticSettings): boolean { + return currentSettings.validate === newSettings.validate + && currentSettings.enableSuggestions && currentSettings.enableSuggestions; +} + class DiagnosticSettings { - private static readonly defaultSettings: LangaugeDiagnosticSettings = { + private static readonly defaultSettings: LanguageDiagnosticSettings = { validate: true, enableSuggestions: true }; - private readonly _languageSettings = new Map(); - - constructor() { - for (const language of allDiagnosticLangauges) { - this._languageSettings.set(language, DiagnosticSettings.defaultSettings); - } - } + private readonly _languageSettings = new Map(); public getValidate(language: DiagnosticLanguage): boolean { return this.get(language).validate; @@ -112,20 +129,19 @@ class DiagnosticSettings { })); } - private get(language: DiagnosticLanguage): LangaugeDiagnosticSettings { + private get(language: DiagnosticLanguage): LanguageDiagnosticSettings { return this._languageSettings.get(language) || DiagnosticSettings.defaultSettings; } - private update(language: DiagnosticLanguage, f: (x: LangaugeDiagnosticSettings) => LangaugeDiagnosticSettings): boolean { + private update(language: DiagnosticLanguage, f: (x: LanguageDiagnosticSettings) => LanguageDiagnosticSettings): boolean { const currentSettings = this.get(language); const newSettings = f(currentSettings); this._languageSettings.set(language, newSettings); - return currentSettings.validate === newSettings.validate - && currentSettings.enableSuggestions && currentSettings.enableSuggestions; + return areLanguageDiagnosticSettingsEqual(currentSettings, newSettings); } } -export class DiagnosticsManager { +export class DiagnosticsManager extends Disposable { private readonly _diagnostics = new ResourceMap(); private readonly _settings = new DiagnosticSettings(); private readonly _currentDiagnostics: vscode.DiagnosticCollection; @@ -136,11 +152,12 @@ export class DiagnosticsManager { constructor( owner: string ) { - this._currentDiagnostics = vscode.languages.createDiagnosticCollection(owner); + super(); + this._currentDiagnostics = this._register(vscode.languages.createDiagnosticCollection(owner)); } public dispose() { - this._currentDiagnostics.dispose(); + super.dispose(); for (const value of this._pendingUpdates.values) { clearTimeout(value); @@ -171,7 +188,7 @@ export class DiagnosticsManager { file: vscode.Uri, language: DiagnosticLanguage, kind: DiagnosticKind, - diagnostics: vscode.Diagnostic[] + diagnostics: ReadonlyArray ): void { let didUpdate = false; const entry = this._diagnostics.get(file); @@ -191,7 +208,7 @@ export class DiagnosticsManager { public configFileDiagnosticsReceived( file: vscode.Uri, - diagnostics: vscode.Diagnostic[] + diagnostics: ReadonlyArray ): void { this._currentDiagnostics.set(file, diagnostics); } @@ -201,7 +218,7 @@ export class DiagnosticsManager { this._diagnostics.delete(resource); } - public getDiagnostics(file: vscode.Uri): vscode.Diagnostic[] { + public getDiagnostics(file: vscode.Uri): ReadonlyArray { return this._currentDiagnostics.get(file) || []; } @@ -227,4 +244,4 @@ export class DiagnosticsManager { this._currentDiagnostics.set(fileDiagnostic.file, fileDiagnostic.getDiagnostics(this._settings)); } } -} \ No newline at end of file +} diff --git a/extensions/typescript-language-features/src/features/directiveCommentCompletions.ts b/extensions/typescript-language-features/src/features/directiveCommentCompletions.ts index 7b30b68a658..0b1ddeca929 100644 --- a/extensions/typescript-language-features/src/features/directiveCommentCompletions.ts +++ b/extensions/typescript-language-features/src/features/directiveCommentCompletions.ts @@ -36,6 +36,8 @@ const directives: Directive[] = [ ]; class DirectiveCommentCompletionProvider implements vscode.CompletionItemProvider { + public static readonly minVersion = API.v230; + constructor( private readonly client: ITypeScriptServiceClient, ) { } @@ -69,7 +71,7 @@ export function register( selector: vscode.DocumentSelector, client: ITypeScriptServiceClient, ) { - return new VersionDependentRegistration(client, API.v230, () => { + return new VersionDependentRegistration(client, DirectiveCommentCompletionProvider.minVersion, () => { return vscode.languages.registerCompletionItemProvider(selector, new DirectiveCommentCompletionProvider(client), '@'); diff --git a/extensions/typescript-language-features/src/features/fileConfigurationManager.ts b/extensions/typescript-language-features/src/features/fileConfigurationManager.ts index d93bdce3367..6d35cd1b92b 100644 --- a/extensions/typescript-language-features/src/features/fileConfigurationManager.ts +++ b/extensions/typescript-language-features/src/features/fileConfigurationManager.ts @@ -9,6 +9,7 @@ import { ITypeScriptServiceClient } from '../typescriptService'; import API from '../utils/api'; import { isTypeScriptDocument } from '../utils/languageModeIds'; import { ResourceMap } from '../utils/resourceMap'; +import { Disposable } from '../utils/dispose'; function objsAreEqual(a: T, b: T): boolean { @@ -33,27 +34,20 @@ function areFileConfigurationsEqual(a: FileConfiguration, b: FileConfiguration): ); } -export default class FileConfigurationManager { - private onDidCloseTextDocumentSub: vscode.Disposable | undefined; +export default class FileConfigurationManager extends Disposable { private readonly formatOptions = new ResourceMap>(); public constructor( private readonly client: ITypeScriptServiceClient ) { - this.onDidCloseTextDocumentSub = vscode.workspace.onDidCloseTextDocument(textDocument => { + super(); + vscode.workspace.onDidCloseTextDocument(textDocument => { // When a document gets closed delete the cached formatting options. // This is necessary since the tsserver now closed a project when its // last file in it closes which drops the stored formatting options // as well. this.formatOptions.delete(textDocument.uri); - }); - } - - public dispose() { - if (this.onDidCloseTextDocumentSub) { - this.onDidCloseTextDocumentSub.dispose(); - this.onDidCloseTextDocumentSub = undefined; - } + }, undefined, this._disposables); } public async ensureConfigurationForDocument( @@ -179,23 +173,25 @@ export default class FileConfigurationManager { return {}; } - const preferences = vscode.workspace.getConfiguration( + const config = vscode.workspace.getConfiguration( isTypeScriptDocument(document) ? 'typescript.preferences' : 'javascript.preferences', document.uri); return { - quotePreference: getQuoteStylePreference(preferences), - importModuleSpecifierPreference: getImportModuleSpecifierPreference(preferences), - allowTextChangesInNewFiles: document.uri.scheme === 'file' + quotePreference: this.getQuoteStylePreference(config), + importModuleSpecifierPreference: getImportModuleSpecifierPreference(config), + allowTextChangesInNewFiles: document.uri.scheme === 'file', + providePrefixAndSuffixTextForRename: config.get('renameShorthandProperties', true), + allowRenameOfImportPath: true, }; } -} -function getQuoteStylePreference(config: vscode.WorkspaceConfiguration) { - switch (config.get('quoteStyle')) { - case 'single': return 'single'; - case 'double': return 'double'; - default: return undefined; + private getQuoteStylePreference(config: vscode.WorkspaceConfiguration) { + switch (config.get('quoteStyle')) { + case 'single': return 'single'; + case 'double': return 'double'; + default: return this.client.apiVersion.gte(API.v333) ? 'auto' : undefined; + } } } diff --git a/extensions/typescript-language-features/src/features/fixAll.ts b/extensions/typescript-language-features/src/features/fixAll.ts new file mode 100644 index 00000000000..8c6f09659c3 --- /dev/null +++ b/extensions/typescript-language-features/src/features/fixAll.ts @@ -0,0 +1,134 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import * as nls from 'vscode-nls'; +import * as Proto from '../protocol'; +import { ITypeScriptServiceClient } from '../typescriptService'; +import API from '../utils/api'; +import { ConfigurationDependentRegistration, VersionDependentRegistration } from '../utils/dependentRegistration'; +import * as typeConverters from '../utils/typeConverters'; +import { DiagnosticsManager } from './diagnostics'; +import FileConfigurationManager from './fileConfigurationManager'; + +const localize = nls.loadMessageBundle(); + +const autoFixableDiagnosticCodes = new Set([ + 2420, // Incorrectly implemented interface + 2552, // Cannot find name +]); + +class TypeScriptAutoFixProvider implements vscode.CodeActionProvider { + + public static readonly metadata: vscode.CodeActionProviderMetadata = { + providedCodeActionKinds: [vscode.CodeActionKind.SourceFixAll] + }; + + constructor( + private readonly client: ITypeScriptServiceClient, + private readonly fileConfigurationManager: FileConfigurationManager, + private readonly diagnosticsManager: DiagnosticsManager, + ) { } + + public async provideCodeActions( + document: vscode.TextDocument, + _range: vscode.Range, + context: vscode.CodeActionContext, + token: vscode.CancellationToken + ): Promise { + if (!context.only || !vscode.CodeActionKind.SourceFixAll.intersects(context.only)) { + return undefined; + } + + const file = this.client.toOpenedFilePath(document); + if (!file) { + return undefined; + } + + const autoFixableDiagnostics = this.getAutoFixableDiagnostics(document); + if (!autoFixableDiagnostics.length) { + return undefined; + } + + const fixAllAction = await this.getFixAllCodeAction(document, file, autoFixableDiagnostics, token); + return fixAllAction ? [fixAllAction] : undefined; + } + + private getAutoFixableDiagnostics( + document: vscode.TextDocument + ): vscode.Diagnostic[] { + if (this.client.bufferSyncSupport.hasPendingDiagnostics(document.uri)) { + return []; + } + + return this.diagnosticsManager.getDiagnostics(document.uri) + .filter(x => autoFixableDiagnosticCodes.has(x.code as number)); + } + + private async getFixAllCodeAction( + document: vscode.TextDocument, + file: string, + diagnostics: ReadonlyArray, + token: vscode.CancellationToken, + ): Promise { + await this.fileConfigurationManager.ensureConfigurationForDocument(document, token); + + const autoFixResponse = await this.getAutoFixEdit(file, diagnostics, token); + if (!autoFixResponse) { + return undefined; + } + const { edit, fixedDiagnostics } = autoFixResponse; + const codeAction = new vscode.CodeAction( + localize('autoFix.label', 'Auto fix'), + vscode.CodeActionKind.SourceFixAll); + codeAction.edit = edit; + codeAction.diagnostics = fixedDiagnostics; + + return codeAction; + } + + private async getAutoFixEdit( + file: string, + diagnostics: ReadonlyArray, + token: vscode.CancellationToken, + ): Promise<{ edit: vscode.WorkspaceEdit, fixedDiagnostics: vscode.Diagnostic[] } | undefined> { + const edit = new vscode.WorkspaceEdit(); + const fixedDiagnostics: vscode.Diagnostic[] = []; + for (const diagnostic of diagnostics) { + const args: Proto.CodeFixRequestArgs = { + ...typeConverters.Range.toFileRangeRequestArgs(file, diagnostic.range), + errorCodes: [+(diagnostic.code!)] + }; + const response = await this.client.execute('getCodeFixes', args, token); + if (response.type !== 'response' || !response.body || response.body.length > 1) { + return undefined; + } + + const fix = response.body[0]; + if (new Set(['fixClassIncorrectlyImplementsInterface', 'spelling']).has(fix.fixName)) { + typeConverters.WorkspaceEdit.withFileCodeEdits(edit, this.client, fix.changes); + fixedDiagnostics.push(diagnostic); + } + } + + if (!fixedDiagnostics.length) { + return undefined; + } + + return { edit, fixedDiagnostics }; + } +} + +export function register( + selector: vscode.DocumentSelector, + client: ITypeScriptServiceClient, + fileConfigurationManager: FileConfigurationManager, + diagnosticsManager: DiagnosticsManager) { + return new VersionDependentRegistration(client, API.v300, () => + new ConfigurationDependentRegistration('typescript', 'experimental.autoFix.enabled', () => + vscode.languages.registerCodeActionsProvider(selector, + new TypeScriptAutoFixProvider(client, fileConfigurationManager, diagnosticsManager), + TypeScriptAutoFixProvider.metadata))); +} diff --git a/extensions/typescript-language-features/src/features/folding.ts b/extensions/typescript-language-features/src/features/folding.ts index 228cb744a53..a00a2db5f00 100644 --- a/extensions/typescript-language-features/src/features/folding.ts +++ b/extensions/typescript-language-features/src/features/folding.ts @@ -11,6 +11,8 @@ import { VersionDependentRegistration } from '../utils/dependentRegistration'; import * as typeConverters from '../utils/typeConverters'; class TypeScriptFoldingProvider implements vscode.FoldingRangeProvider { + public static readonly minVersion = API.v280; + public constructor( private readonly client: ITypeScriptServiceClient ) { } @@ -75,7 +77,7 @@ export function register( selector: vscode.DocumentSelector, client: ITypeScriptServiceClient, ): vscode.Disposable { - return new VersionDependentRegistration(client, API.v280, () => { + return new VersionDependentRegistration(client, TypeScriptFoldingProvider.minVersion, () => { return vscode.languages.registerFoldingRangeProvider(selector, new TypeScriptFoldingProvider(client)); }); diff --git a/extensions/typescript-language-features/src/features/hover.ts b/extensions/typescript-language-features/src/features/hover.ts index fbd569cdb69..5077f9648a0 100644 --- a/extensions/typescript-language-features/src/features/hover.ts +++ b/extensions/typescript-language-features/src/features/hover.ts @@ -27,7 +27,7 @@ class TypeScriptHoverProvider implements vscode.HoverProvider { } const args = typeConverters.Position.toFileLocationRequestArgs(filepath, position); - const response = await this.client.interuptGetErr(() => this.client.execute('quickinfo', args, token)); + const response = await this.client.interruptGetErr(() => this.client.execute('quickinfo', args, token)); if (response.type !== 'response' || !response.body) { return undefined; } diff --git a/extensions/typescript-language-features/src/features/implementations.ts b/extensions/typescript-language-features/src/features/implementations.ts index d750587ea8d..7b7dc130175 100644 --- a/extensions/typescript-language-features/src/features/implementations.ts +++ b/extensions/typescript-language-features/src/features/implementations.ts @@ -10,6 +10,8 @@ import { VersionDependentRegistration } from '../utils/dependentRegistration'; import DefinitionProviderBase from './definitionProviderBase'; class TypeScriptImplementationProvider extends DefinitionProviderBase implements vscode.ImplementationProvider { + public static readonly minVersion = API.v220; + public provideImplementation(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise { return this.getSymbolLocations('implementation', document, position, token); } @@ -19,7 +21,7 @@ export function register( selector: vscode.DocumentSelector, client: ITypeScriptServiceClient, ) { - return new VersionDependentRegistration(client, API.v220, () => { + return new VersionDependentRegistration(client, TypeScriptImplementationProvider.minVersion, () => { return vscode.languages.registerImplementationProvider(selector, new TypeScriptImplementationProvider(client)); }); diff --git a/extensions/typescript-language-features/src/features/implementationsCodeLens.ts b/extensions/typescript-language-features/src/features/implementationsCodeLens.ts index e2f7dc2b531..c732ade5223 100644 --- a/extensions/typescript-language-features/src/features/implementationsCodeLens.ts +++ b/extensions/typescript-language-features/src/features/implementationsCodeLens.ts @@ -17,6 +17,7 @@ import * as typeConverters from '../utils/typeConverters'; const localize = nls.loadMessageBundle(); export default class TypeScriptImplementationsCodeLensProvider extends TypeScriptBaseCodeLensProvider { + public static readonly minVersion = API.v220; public async resolveCodeLens( inputCodeLens: vscode.CodeLens, @@ -25,7 +26,7 @@ export default class TypeScriptImplementationsCodeLensProvider extends TypeScrip const codeLens = inputCodeLens as ReferencesCodeLens; const args = typeConverters.Position.toFileLocationRequestArgs(codeLens.file, codeLens.range.start); - const response = await this.client.execute('implementation', args, token, /* lowPriority */ true); + const response = await this.client.execute('implementation', args, token, { lowPriority: true }); if (response.type !== 'response' || !response.body) { codeLens.command = response.type === 'cancelled' ? TypeScriptBaseCodeLensProvider.cancelledCommand @@ -95,7 +96,7 @@ export function register( client: ITypeScriptServiceClient, cachedResponse: CachedResponse, ) { - return new VersionDependentRegistration(client, API.v220, () => + return new VersionDependentRegistration(client, TypeScriptImplementationsCodeLensProvider.minVersion, () => new ConfigurationDependentRegistration(modeId, 'implementationsCodeLens.enabled', () => { return vscode.languages.registerCodeLensProvider(selector, new TypeScriptImplementationsCodeLensProvider(client, cachedResponse)); diff --git a/extensions/typescript-language-features/src/features/jsDocCompletions.ts b/extensions/typescript-language-features/src/features/jsDocCompletions.ts index e84b27ed2b8..36f7a751522 100644 --- a/extensions/typescript-language-features/src/features/jsDocCompletions.ts +++ b/extensions/typescript-language-features/src/features/jsDocCompletions.ts @@ -112,9 +112,10 @@ export function templateToSnippet(template: string): vscode.SnippetString { export function register( selector: vscode.DocumentSelector, + modeId: string, client: ITypeScriptServiceClient, ): vscode.Disposable { - return new ConfigurationDependentRegistration('jsDocCompletion', 'enabled', () => { + return new ConfigurationDependentRegistration(modeId, 'suggest.completeJSDocs', () => { return vscode.languages.registerCompletionItemProvider(selector, new JsDocCompletionProvider(client), '*'); diff --git a/extensions/typescript-language-features/src/features/languageConfiguration.ts b/extensions/typescript-language-features/src/features/languageConfiguration.ts index 33691a615cc..59fefa1007b 100644 --- a/extensions/typescript-language-features/src/features/languageConfiguration.ts +++ b/extensions/typescript-language-features/src/features/languageConfiguration.ts @@ -42,6 +42,11 @@ const jsTsLanguageConfiguration: vscode.LanguageConfiguration = { // e.g. *-----*/| beforeText: /^(\t|[ ])*[ ]\*[^/]*\*\/\s*$/, action: { indentAction: vscode.IndentAction.None, removeText: 1 }, + }, + { + beforeText: /^\s*(\bcase\s.+:|\bdefault:)$/, + afterText: /^(?!\s*(\bcase\b|\bdefault\b))/, + action: { indentAction: vscode.IndentAction.Indent }, } ] }; @@ -52,14 +57,26 @@ const jsxTagsLanguageConfiguration: vscode.LanguageConfiguration = { wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g, onEnterRules: [ { - beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), + beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\w][_:\\w\\-.\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>$/i, action: { indentAction: vscode.IndentAction.IndentOutdent } }, { - beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), + beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\w][_:\\w\\-.\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), action: { indentAction: vscode.IndentAction.Indent } - } + }, + { + // `beforeText` only applies to tokens of a given language. Since we are dealing with jsx-tags, + // make sure we apply to the closing `>` of a tag so that mixed language spans + // such as `
    ` are handled properly. + beforeText: /^>$/, + afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>$/i, + action: { indentAction: vscode.IndentAction.IndentOutdent } + }, + { + beforeText: /^>$/, + action: { indentAction: vscode.IndentAction.Indent } + }, ], }; diff --git a/extensions/typescript-language-features/src/features/organizeImports.ts b/extensions/typescript-language-features/src/features/organizeImports.ts index 7a4cdf7bc46..bb7880800a6 100644 --- a/extensions/typescript-language-features/src/features/organizeImports.ts +++ b/extensions/typescript-language-features/src/features/organizeImports.ts @@ -46,7 +46,7 @@ class OrganizeImportsCommand implements Command { } } }; - const response = await this.client.execute('organizeImports', args, nulToken); + const response = await this.client.interruptGetErr(() => this.client.execute('organizeImports', args, nulToken)); if (response.type !== 'response' || !response.body) { return false; } @@ -57,6 +57,8 @@ class OrganizeImportsCommand implements Command { } export class OrganizeImportsCodeActionProvider implements vscode.CodeActionProvider { + public static readonly minVersion = API.v280; + public constructor( private readonly client: ITypeScriptServiceClient, commandManager: CommandManager, @@ -89,7 +91,7 @@ export class OrganizeImportsCodeActionProvider implements vscode.CodeActionProvi this.fileConfigManager.ensureConfigurationForDocument(document, token); const action = new vscode.CodeAction( - localize('oraganizeImportsAction.title', "Organize Imports"), + localize('organizeImportsAction.title', "Organize Imports"), vscode.CodeActionKind.SourceOrganizeImports); action.command = { title: '', command: OrganizeImportsCommand.Id, arguments: [file] }; return [action]; @@ -103,7 +105,7 @@ export function register( fileConfigurationManager: FileConfigurationManager, telemetryReporter: TelemetryReporter, ) { - return new VersionDependentRegistration(client, API.v280, () => { + return new VersionDependentRegistration(client, OrganizeImportsCodeActionProvider.minVersion, () => { const organizeImportsProvider = new OrganizeImportsCodeActionProvider(client, commandManager, fileConfigurationManager, telemetryReporter); return vscode.languages.registerCodeActionsProvider(selector, organizeImportsProvider, diff --git a/extensions/typescript-language-features/src/features/quickFix.ts b/extensions/typescript-language-features/src/features/quickFix.ts index f06706b7a41..6ce9f199704 100644 --- a/extensions/typescript-language-features/src/features/quickFix.ts +++ b/extensions/typescript-language-features/src/features/quickFix.ts @@ -128,8 +128,8 @@ class DiagnosticsSet { } class CodeActionSet { - private _actions = new Set(); - private _fixAllActions = new Map<{}, vscode.CodeAction>(); + private readonly _actions = new Set(); + private readonly _fixAllActions = new Map<{}, vscode.CodeAction>(); public get values(): Iterable { return this._actions; @@ -142,7 +142,7 @@ class CodeActionSet { public addFixAllAction(fixId: {}, action: vscode.CodeAction) { const existing = this._fixAllActions.get(fixId); if (existing) { - // reinsert action at back + // reinsert action at back of actions list this._actions.delete(existing); } this.addAction(action); @@ -174,6 +174,7 @@ class SupportedCodeActionProvider { } class TypeScriptQuickFixProvider implements vscode.CodeActionProvider { + public static readonly minVersion = API.v213; public static readonly metadata: vscode.CodeActionProviderMetadata = { providedCodeActionKinds: [vscode.CodeActionKind.QuickFix] @@ -216,33 +217,33 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider { await this.formattingConfigurationManager.ensureConfigurationForDocument(document, token); - const results: vscode.CodeAction[] = []; + const results = new CodeActionSet(); for (const diagnostic of fixableDiagnostics.values) { - results.push(...await this.getFixesForDiagnostic(document, file, diagnostic, token)); + await this.getFixesForDiagnostic(document, file, diagnostic, results, token); } - return results; + return Array.from(results.values); } private async getFixesForDiagnostic( document: vscode.TextDocument, file: string, diagnostic: vscode.Diagnostic, - token: vscode.CancellationToken - ): Promise> { + results: CodeActionSet, + token: vscode.CancellationToken, + ): Promise { const args: Proto.CodeFixRequestArgs = { ...typeConverters.Range.toFileRangeRequestArgs(file, diagnostic.range), errorCodes: [+(diagnostic.code!)] }; const response = await this.client.execute('getCodeFixes', args, token); if (response.type !== 'response' || !response.body) { - return []; + return results; } - const results = new CodeActionSet(); for (const tsCodeFix of response.body) { - this.addAllFixesForTsCodeAction(results, document, file, diagnostic, tsCodeFix); + this.addAllFixesForTsCodeAction(results, document, file, diagnostic, tsCodeFix as Proto.CodeFixAction); } - return results.values; + return results; } private addAllFixesForTsCodeAction( @@ -250,7 +251,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider { document: vscode.TextDocument, file: string, diagnostic: vscode.Diagnostic, - tsAction: Proto.CodeAction + tsAction: Proto.CodeFixAction ): CodeActionSet { results.addAction(this.getSingleFixForTsCodeAction(diagnostic, tsAction)); this.addFixAllForTsCodeAction(results, document, file, diagnostic, tsAction as Proto.CodeFixAction); @@ -259,7 +260,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider { private getSingleFixForTsCodeAction( diagnostic: vscode.Diagnostic, - tsAction: Proto.CodeAction + tsAction: Proto.CodeFixAction ): vscode.CodeAction { const codeAction = new vscode.CodeAction(tsAction.description, vscode.CodeActionKind.QuickFix); codeAction.edit = getEditForCodeAction(this.client, tsAction); @@ -269,6 +270,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider { arguments: [tsAction], title: '' }; + codeAction.isPreferred = isPreferredFix(tsAction); return codeAction; } @@ -279,7 +281,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider { diagnostic: vscode.Diagnostic, tsAction: Proto.CodeFixAction, ): CodeActionSet { - if (!tsAction.fixId || this.client.apiVersion.lt(API.v270) || results.hasFixAllAction(results)) { + if (!tsAction.fixId || this.client.apiVersion.lt(API.v270) || results.hasFixAllAction(tsAction.fixId)) { return results; } @@ -302,6 +304,22 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider { } } +const preferredFixes = new Set([ + 'annotateWithTypeFromJSDoc', + 'constructorForDerivedNeedSuperCall', + 'extendsInterfaceBecomesImplements', + 'fixAwaitInSyncFunction', + 'fixClassIncorrectlyImplementsInterface', + 'fixUnreachableCode', + 'forgottenThisPropertyAccess', + 'spelling', + 'unusedIdentifier', + 'addMissingAwait', +]); +function isPreferredFix(tsAction: Proto.CodeFixAction): boolean { + return preferredFixes.has(tsAction.fixName); +} + export function register( selector: vscode.DocumentSelector, client: ITypeScriptServiceClient, @@ -310,7 +328,7 @@ export function register( diagnosticsManager: DiagnosticsManager, telemetryReporter: TelemetryReporter ) { - return new VersionDependentRegistration(client, API.v213, () => + return new VersionDependentRegistration(client, TypeScriptQuickFixProvider.minVersion, () => vscode.languages.registerCodeActionsProvider(selector, new TypeScriptQuickFixProvider(client, fileConfigurationManager, commandManager, diagnosticsManager, telemetryReporter), TypeScriptQuickFixProvider.metadata)); diff --git a/extensions/typescript-language-features/src/features/refactor.ts b/extensions/typescript-language-features/src/features/refactor.ts index 5dfdc3de2e2..6b0d33a2bb9 100644 --- a/extensions/typescript-language-features/src/features/refactor.ts +++ b/extensions/typescript-language-features/src/features/refactor.ts @@ -4,15 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; +import * as nls from 'vscode-nls'; import * as Proto from '../protocol'; import { ITypeScriptServiceClient } from '../typescriptService'; import API from '../utils/api'; +import { nulToken } from '../utils/cancellation'; import { Command, CommandManager } from '../utils/commandManager'; import { VersionDependentRegistration } from '../utils/dependentRegistration'; import TelemetryReporter from '../utils/telemetry'; import * as typeConverters from '../utils/typeConverters'; import FormattingOptionsManager from './fileConfigurationManager'; -import { nulToken } from '../utils/cancellation'; +import { file } from '../utils/fileSchemes'; + +const localize = nls.loadMessageBundle(); class ApplyRefactoringCommand implements Command { @@ -49,7 +53,12 @@ class ApplyRefactoringCommand implements Command { action, }; const response = await this.client.execute('getEditsForRefactor', args, nulToken); - if (response.type !== 'response' || !response.body || !response.body.edits.length) { + if (response.type !== 'response' || !response.body) { + return false; + } + + if (!response.body.edits.length) { + vscode.window.showErrorMessage(localize('refactoringFailed', "Could not apply refactoring")); return false; } @@ -71,7 +80,10 @@ class ApplyRefactoringCommand implements Command { private async toWorkspaceEdit(body: Proto.RefactorEditInfo) { const workspaceEdit = new vscode.WorkspaceEdit(); for (const edit of body.edits) { - workspaceEdit.createFile(this.client.toResource(edit.fileName), { ignoreIfExists: true }); + const resource = this.client.toResource(edit.fileName); + if (resource.scheme === file) { + workspaceEdit.createFile(resource, { ignoreIfExists: true }); + } } typeConverters.WorkspaceEdit.withFileCodeEdits(workspaceEdit, this.client, body.edits); return workspaceEdit; @@ -104,8 +116,11 @@ class SelectRefactorCommand implements Command { } class TypeScriptRefactorProvider implements vscode.CodeActionProvider { + public static readonly minVersion = API.v240; + private static readonly extractFunctionKind = vscode.CodeActionKind.RefactorExtract.append('function'); private static readonly extractConstantKind = vscode.CodeActionKind.RefactorExtract.append('constant'); + private static readonly extractTypeKind = vscode.CodeActionKind.RefactorExtract.append('type'); private static readonly moveKind = vscode.CodeActionKind.Refactor.append('move'); constructor( @@ -138,7 +153,7 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider { } const args: Proto.GetApplicableRefactorsRequestArgs = typeConverters.Range.toFileRangeRequestArgs(file, rangeOrSelection); - const response = await this.client.interuptGetErr(() => { + const response = await this.client.interruptGetErr(() => { this.formattingOptionsManager.ensureConfigurationForDocument(document, token); return this.client.execute('getApplicableRefactors', args, token); @@ -188,6 +203,7 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider { command: ApplyRefactoringCommand.ID, arguments: [document, file, info.name, action.name, rangeOrSelection], }; + codeAction.isPreferred = TypeScriptRefactorProvider.isPreferred(action); return codeAction; } @@ -206,9 +222,23 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider { return TypeScriptRefactorProvider.extractConstantKind; } else if (refactor.name.startsWith('Move')) { return TypeScriptRefactorProvider.moveKind; + } else if (refactor.name.includes('Extract to type alias')) { + return TypeScriptRefactorProvider.extractTypeKind; } return vscode.CodeActionKind.Refactor; } + + private static isPreferred( + action: Proto.RefactorActionInfo + ): boolean { + if (action.name.startsWith('constant_')) { + return action.name.endsWith('scope_0'); + } + if (action.name.includes('Extract to type alias')) { + return true; + } + return false; + } } export function register( @@ -218,7 +248,7 @@ export function register( commandManager: CommandManager, telemetryReporter: TelemetryReporter, ) { - return new VersionDependentRegistration(client, API.v240, () => { + return new VersionDependentRegistration(client, TypeScriptRefactorProvider.minVersion, () => { return vscode.languages.registerCodeActionsProvider(selector, new TypeScriptRefactorProvider(client, formattingOptionsManager, commandManager, telemetryReporter), TypeScriptRefactorProvider.metadata); diff --git a/extensions/typescript-language-features/src/features/referencesCodeLens.ts b/extensions/typescript-language-features/src/features/referencesCodeLens.ts index 7c256e3064f..65c2cd5eb7f 100644 --- a/extensions/typescript-language-features/src/features/referencesCodeLens.ts +++ b/extensions/typescript-language-features/src/features/referencesCodeLens.ts @@ -17,11 +17,12 @@ import { CachedResponse } from '../tsServer/cachedResponse'; const localize = nls.loadMessageBundle(); class TypeScriptReferencesCodeLensProvider extends TypeScriptBaseCodeLensProvider { + public static readonly minVersion = API.v206; public async resolveCodeLens(inputCodeLens: vscode.CodeLens, token: vscode.CancellationToken): Promise { const codeLens = inputCodeLens as ReferencesCodeLens; const args = typeConverters.Position.toFileLocationRequestArgs(codeLens.file, codeLens.range.start); - const response = await this.client.execute('references', args, token, /* lowPriority */ true); + const response = await this.client.execute('references', args, token, { lowPriority: true }); if (response.type !== 'response' || !response.body) { codeLens.command = response.type === 'cancelled' ? TypeScriptBaseCodeLensProvider.cancelledCommand @@ -98,7 +99,7 @@ export function register( client: ITypeScriptServiceClient, cachedResponse: CachedResponse, ) { - return new VersionDependentRegistration(client, API.v206, () => + return new VersionDependentRegistration(client, TypeScriptReferencesCodeLensProvider.minVersion, () => new ConfigurationDependentRegistration(modeId, 'referencesCodeLens.enabled', () => { return vscode.languages.registerCodeLensProvider(selector, new TypeScriptReferencesCodeLensProvider(client, cachedResponse)); diff --git a/extensions/typescript-language-features/src/features/rename.ts b/extensions/typescript-language-features/src/features/rename.ts index 7b1c0ac791e..aff2c508c53 100644 --- a/extensions/typescript-language-features/src/features/rename.ts +++ b/extensions/typescript-language-features/src/features/rename.ts @@ -10,12 +10,14 @@ import * as Proto from '../protocol'; import { ITypeScriptServiceClient, ServerResponse } from '../typescriptService'; import API from '../utils/api'; import * as typeConverters from '../utils/typeConverters'; +import FileConfigurationManager from './fileConfigurationManager'; const localize = nls.loadMessageBundle(); class TypeScriptRenameProvider implements vscode.RenameProvider { public constructor( - private readonly client: ITypeScriptServiceClient + private readonly client: ITypeScriptServiceClient, + private readonly fileConfigurationManager: FileConfigurationManager ) { } public async prepareRename( @@ -36,8 +38,7 @@ class TypeScriptRenameProvider implements vscode.RenameProvider { if (this.client.apiVersion.gte(API.v310)) { const triggerSpan = renameInfo.triggerSpan; if (triggerSpan) { - const range = typeConverters.Range.fromTextSpan(triggerSpan); - return range; + return typeConverters.Range.fromTextSpan(triggerSpan); } } @@ -78,7 +79,7 @@ class TypeScriptRenameProvider implements vscode.RenameProvider { document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken - ): Promise | undefined> { + ): Promise | undefined> { const file = this.client.toOpenedFilePath(document); if (!file) { return undefined; @@ -90,7 +91,10 @@ class TypeScriptRenameProvider implements vscode.RenameProvider { findInComments: false }; - return this.client.execute('rename', args, token); + return this.client.interruptGetErr(() => { + this.fileConfigurationManager.ensureConfigurationForDocument(document, token); + return this.client.execute('rename', args, token); + }); } private updateLocs( @@ -142,6 +146,8 @@ class TypeScriptRenameProvider implements vscode.RenameProvider { export function register( selector: vscode.DocumentSelector, client: ITypeScriptServiceClient, + fileConfigurationManager: FileConfigurationManager, ) { - return vscode.languages.registerRenameProvider(selector, new TypeScriptRenameProvider(client)); + return vscode.languages.registerRenameProvider(selector, + new TypeScriptRenameProvider(client, fileConfigurationManager)); } diff --git a/extensions/typescript-language-features/src/features/signatureHelp.ts b/extensions/typescript-language-features/src/features/signatureHelp.ts index bf1e380eb31..189185a37fc 100644 --- a/extensions/typescript-language-features/src/features/signatureHelp.ts +++ b/extensions/typescript-language-features/src/features/signatureHelp.ts @@ -33,7 +33,7 @@ class TypeScriptSignatureHelpProvider implements vscode.SignatureHelpProvider { ...typeConverters.Position.toFileLocationRequestArgs(filepath, position), triggerReason: toTsTriggerReason(context) }; - const response = await this.client.interuptGetErr(() => this.client.execute('signatureHelp', args, token)); + const response = await this.client.interruptGetErr(() => this.client.execute('signatureHelp', args, token)); if (response.type !== 'response' || !response.body) { return undefined; } diff --git a/extensions/typescript-language-features/src/features/smartSelect.ts b/extensions/typescript-language-features/src/features/smartSelect.ts new file mode 100644 index 00000000000..3d05d1309a2 --- /dev/null +++ b/extensions/typescript-language-features/src/features/smartSelect.ts @@ -0,0 +1,57 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import * as Proto from '../protocol'; +import { ITypeScriptServiceClient } from '../typescriptService'; +import API from '../utils/api'; +import { VersionDependentRegistration } from '../utils/dependentRegistration'; +import * as typeConverters from '../utils/typeConverters'; + +class SmartSelection implements vscode.SelectionRangeProvider { + public static readonly minVersion = API.v350; + + public constructor( + private readonly client: ITypeScriptServiceClient + ) { } + + public async provideSelectionRanges( + document: vscode.TextDocument, + positions: vscode.Position[], + token: vscode.CancellationToken, + ): Promise { + const file = this.client.toOpenedFilePath(document); + if (!file) { + return undefined; + } + + const args: Proto.SelectionRangeRequestArgs = { + file, + locations: positions.map(typeConverters.Position.toLocation) + }; + const response = await this.client.execute('selectionRange', args, token); + if (response.type !== 'response' || !response.body) { + return undefined; + } + return response.body.map(SmartSelection.convertSelectionRange); + } + + private static convertSelectionRange( + selectionRange: Proto.SelectionRange + ): vscode.SelectionRange { + return new vscode.SelectionRange( + typeConverters.Range.fromTextSpan(selectionRange.textSpan), + selectionRange.parent ? SmartSelection.convertSelectionRange(selectionRange.parent) : undefined, + ); + } +} + +export function register( + selector: vscode.DocumentSelector, + client: ITypeScriptServiceClient, +) { + return new VersionDependentRegistration(client, SmartSelection.minVersion, () => + vscode.languages.registerSelectionRangeProvider(selector, new SmartSelection(client))); +} \ No newline at end of file diff --git a/extensions/typescript-language-features/src/features/tagClosing.ts b/extensions/typescript-language-features/src/features/tagClosing.ts index e4df1264ccf..1123b175531 100644 --- a/extensions/typescript-language-features/src/features/tagClosing.ts +++ b/extensions/typescript-language-features/src/features/tagClosing.ts @@ -12,6 +12,7 @@ import { Disposable } from '../utils/dispose'; import * as typeConverters from '../utils/typeConverters'; class TagClosing extends Disposable { + public static readonly minVersion = API.v300; private _disposed = false; private _timeout: NodeJS.Timer | undefined = undefined; @@ -45,7 +46,7 @@ class TagClosing extends Disposable { private onDidChangeTextDocument( document: vscode.TextDocument, - changes: vscode.TextDocumentContentChangeEvent[] + changes: readonly vscode.TextDocumentContentChangeEvent[] ) { const activeDocument = vscode.window.activeTextEditor && vscode.window.activeTextEditor.document; if (document !== activeDocument || changes.length === 0) { @@ -144,6 +145,7 @@ export class ActiveDocumentDependentRegistration extends Disposable { super(); this._registration = this._register(new ConditionalRegistration(register)); vscode.window.onDidChangeActiveTextEditor(this.update, this, this._disposables); + vscode.workspace.onDidOpenTextDocument(this.onDidOpenDocument, this, this._disposables); this.update(); } @@ -152,6 +154,13 @@ export class ActiveDocumentDependentRegistration extends Disposable { const enabled = !!(editor && vscode.languages.match(this.selector, editor.document)); this._registration.update(enabled); } + + private onDidOpenDocument(openedDocument: vscode.TextDocument) { + if (vscode.window.activeTextEditor && vscode.window.activeTextEditor.document === openedDocument) { + // The active document's language may have changed + this.update(); + } + } } export function register( @@ -159,7 +168,7 @@ export function register( modeId: string, client: ITypeScriptServiceClient, ) { - return new VersionDependentRegistration(client, API.v300, () => + return new VersionDependentRegistration(client, TagClosing.minVersion, () => new ConfigurationDependentRegistration(modeId, 'autoClosingTags', () => new ActiveDocumentDependentRegistration(selector, () => new TagClosing(client)))); diff --git a/extensions/typescript-language-features/src/features/task.ts b/extensions/typescript-language-features/src/features/task.ts index c71f3c4435d..e47ee6d7fdc 100644 --- a/extensions/typescript-language-features/src/features/task.ts +++ b/extensions/typescript-language-features/src/features/task.ts @@ -7,12 +7,12 @@ import * as fs from 'fs'; import * as path from 'path'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; +import * as jsonc from 'jsonc-parser'; import { ITypeScriptServiceClient } from '../typescriptService'; import { Lazy } from '../utils/lazy'; import { isImplicitProjectConfigFile } from '../utils/tsconfig'; import TsConfigProvider, { TSConfig } from '../utils/tsconfigProvider'; - const localize = nls.loadMessageBundle(); type AutoDetect = 'on' | 'off' | 'build' | 'watch'; @@ -34,7 +34,7 @@ interface TypeScriptTaskDefinition extends vscode.TaskDefinition { /** * Provides tasks for building `tsconfig.json` files in a project. */ -class TscTaskProvider implements vscode.TaskProvider { +export default class TscTaskProvider implements vscode.TaskProvider { private autoDetect: AutoDetect = 'on'; private readonly tsconfigProvider: TsConfigProvider; private readonly disposables: vscode.Disposable[] = []; @@ -54,7 +54,7 @@ class TscTaskProvider implements vscode.TaskProvider { public async provideTasks(token: vscode.CancellationToken): Promise { const folders = vscode.workspace.workspaceFolders; - if (!folders || !folders.length) { + if ((this.autoDetect === 'off') || !folders || !folders.length) { return []; } @@ -69,7 +69,30 @@ class TscTaskProvider implements vscode.TaskProvider { return tasks; } - public resolveTask(_task: vscode.Task): vscode.Task | undefined { + public async resolveTask(_task: vscode.Task): Promise { + const definition = _task.definition; + const badTsconfig = /\\tsconfig.*\.json/; + if (badTsconfig.exec(definition.tsconfig) !== null) { + // Warn that the task has the wrong slash type + vscode.window.showWarningMessage(localize('badTsConfig', "Typescript Task in tasks.json contains \"\\\\\". Typescript tasks tsconfig must use \"/\"")); + return undefined; + } + + const typescriptTask = (_task.definition).tsconfig; + if (typescriptTask) { + if (_task.scope === undefined || _task.scope === vscode.TaskScope.Global || _task.scope === vscode.TaskScope.Workspace) { + // scope is required to be a WorkspaceFolder for resolveTask + return undefined; + } + const kind: TypeScriptTaskDefinition = (_task.definition); + const tsconfigUri: vscode.Uri = _task.scope.uri.with({ path: _task.scope.uri.path + '/' + kind.tsconfig }); + const tsconfig: TSConfig = { + path: tsconfigUri.fsPath, + posixPath: tsconfigUri.path, + workspaceFolder: _task.scope + }; + return this.getTasksForProjectAndDefinition(tsconfig, kind); + } return undefined; } @@ -94,6 +117,7 @@ class TscTaskProvider implements vscode.TaskProvider { const uri = editor.document.uri; return [{ path: uri.fsPath, + posixPath: uri.path, workspaceFolder: vscode.workspace.getWorkspaceFolder(uri) }]; } @@ -119,6 +143,7 @@ class TscTaskProvider implements vscode.TaskProvider { const folder = vscode.workspace.getWorkspaceFolder(uri); return [{ path: normalizedConfigPath, + posixPath: uri.path, workspaceFolder: folder }]; } @@ -169,6 +194,32 @@ class TscTaskProvider implements vscode.TaskProvider { return undefined; } + private getBuildTask(workspaceFolder: vscode.WorkspaceFolder | undefined, label: string, command: string, args: string[], buildTaskidentifier: TypeScriptTaskDefinition): vscode.Task { + const buildTask = new vscode.Task( + buildTaskidentifier, + workspaceFolder || vscode.TaskScope.Workspace, + localize('buildTscLabel', 'build - {0}', label), + 'tsc', + new vscode.ShellExecution(command, args), + '$tsc'); + buildTask.group = vscode.TaskGroup.Build; + buildTask.isBackground = false; + return buildTask; + } + + private getWatchTask(workspaceFolder: vscode.WorkspaceFolder | undefined, label: string, command: string, args: string[], watchTaskidentifier: TypeScriptTaskDefinition) { + const watchTask = new vscode.Task( + watchTaskidentifier, + workspaceFolder || vscode.TaskScope.Workspace, + localize('buildAndWatchTscLabel', 'watch - {0}', label), + 'tsc', + new vscode.ShellExecution(command, [...args, '--watch']), + '$tsc-watch'); + watchTask.group = vscode.TaskGroup.Build; + watchTask.isBackground = true; + return watchTask; + } + private async getTasksForProject(project: TSConfig): Promise { const command = await TscTaskProvider.getCommand(project); const args = await this.getBuildShellArgs(project); @@ -177,36 +228,33 @@ class TscTaskProvider implements vscode.TaskProvider { const tasks: vscode.Task[] = []; if (this.autoDetect === 'build' || this.autoDetect === 'on') { - const buildTaskidentifier: TypeScriptTaskDefinition = { type: 'typescript', tsconfig: label }; - const buildTask = new vscode.Task( - buildTaskidentifier, - project.workspaceFolder || vscode.TaskScope.Workspace, - localize('buildTscLabel', 'build - {0}', label), - 'tsc', - new vscode.ShellExecution(command, args), - '$tsc'); - buildTask.group = vscode.TaskGroup.Build; - buildTask.isBackground = false; - tasks.push(buildTask); + tasks.push(this.getBuildTask(project.workspaceFolder, label, command, args, { type: 'typescript', tsconfig: label })); } if (this.autoDetect === 'watch' || this.autoDetect === 'on') { - const watchTaskidentifier: TypeScriptTaskDefinition = { type: 'typescript', tsconfig: label, option: 'watch' }; - const watchTask = new vscode.Task( - watchTaskidentifier, - project.workspaceFolder || vscode.TaskScope.Workspace, - localize('buildAndWatchTscLabel', 'watch - {0}', label), - 'tsc', - new vscode.ShellExecution(command, ['--watch', ...args]), - '$tsc-watch'); - watchTask.group = vscode.TaskGroup.Build; - watchTask.isBackground = true; - tasks.push(watchTask); + + tasks.push(this.getWatchTask(project.workspaceFolder, label, command, args, { type: 'typescript', tsconfig: label, option: 'watch' })); } return tasks; } + private async getTasksForProjectAndDefinition(project: TSConfig, definition: TypeScriptTaskDefinition): Promise { + const command = await TscTaskProvider.getCommand(project); + const args = await this.getBuildShellArgs(project); + const label = this.getLabelForTasks(project); + + let task: vscode.Task | undefined; + + if (definition.option === undefined) { + task = this.getBuildTask(project.workspaceFolder, label, command, args, definition); + } else if (definition.option === 'watch') { + task = this.getWatchTask(project.workspaceFolder, label, command, args, definition); + } + + return task; + } + private getBuildShellArgs(project: TSConfig): Promise> { const defaultArgs = ['-p', project.path]; return new Promise>((resolve) => { @@ -216,7 +264,7 @@ class TscTaskProvider implements vscode.TaskProvider { } try { - const tsconfig = JSON.parse(result.toString()); + const tsconfig = jsonc.parse(result.toString()); if (tsconfig.references) { return resolve(['-b', project.path]); } @@ -230,9 +278,11 @@ class TscTaskProvider implements vscode.TaskProvider { private getLabelForTasks(project: TSConfig): string { if (project.workspaceFolder) { - return path.relative(project.workspaceFolder.uri.fsPath, project.path); + const workspaceNormalizedUri = vscode.Uri.file(path.normalize(project.workspaceFolder.uri.fsPath)); // Make sure the drive letter is lowercase + return path.posix.relative(workspaceNormalizedUri.path, project.posixPath); } - return project.path; + + return project.posixPath; } private onConfigurationChanged(): void { @@ -240,36 +290,3 @@ class TscTaskProvider implements vscode.TaskProvider { this.autoDetect = typeof type === 'undefined' ? 'on' : type; } } - -/** - * Manages registrations of TypeScript task providers with VS Code. - */ -export default class TypeScriptTaskProviderManager { - private taskProviderSub: vscode.Disposable | undefined = undefined; - private readonly disposables: vscode.Disposable[] = []; - - constructor( - private readonly client: Lazy - ) { - vscode.workspace.onDidChangeConfiguration(this.onConfigurationChanged, this, this.disposables); - this.onConfigurationChanged(); - } - - dispose() { - if (this.taskProviderSub) { - this.taskProviderSub.dispose(); - this.taskProviderSub = undefined; - } - this.disposables.forEach(x => x.dispose()); - } - - private onConfigurationChanged() { - const autoDetect = vscode.workspace.getConfiguration('typescript.tsc').get('autoDetect'); - if (this.taskProviderSub && autoDetect === 'off') { - this.taskProviderSub.dispose(); - this.taskProviderSub = undefined; - } else if (!this.taskProviderSub && autoDetect !== 'off') { - this.taskProviderSub = vscode.workspace.registerTaskProvider('typescript', new TscTaskProvider(this.client)); - } - } -} \ No newline at end of file diff --git a/extensions/typescript-language-features/src/features/tsconfig.ts b/extensions/typescript-language-features/src/features/tsconfig.ts index a7e89ea1332..2a47c0887bd 100644 --- a/extensions/typescript-language-features/src/features/tsconfig.ts +++ b/extensions/typescript-language-features/src/features/tsconfig.ts @@ -26,23 +26,30 @@ class TsconfigLinkProvider implements vscode.DocumentLinkProvider { } return [ - this.getExendsLink(document, root), + this.getExtendsLink(document, root), ...this.getFilesLinks(document, root), ...this.getReferencesLinks(document, root) ].filter(x => !!x) as vscode.DocumentLink[]; } - private getExendsLink(document: vscode.TextDocument, root: jsonc.Node): vscode.DocumentLink | undefined { + private getExtendsLink(document: vscode.TextDocument, root: jsonc.Node): vscode.DocumentLink | undefined { const extendsNode = jsonc.findNodeAtLocation(root, ['extends']); if (!this.isPathValue(extendsNode)) { return undefined; } + if (extendsNode.value.startsWith('.')) { + return new vscode.DocumentLink( + this.getRange(document, extendsNode), + vscode.Uri.file(join(dirname(document.uri.fsPath), extendsNode.value + (extendsNode.value.endsWith('.json') ? '' : '.json'))) + ); + } + + const workspaceFolderPath = vscode.workspace.getWorkspaceFolder(document.uri)!.uri.fsPath; return new vscode.DocumentLink( this.getRange(document, extendsNode), - basename(extendsNode.value).match('.json$') - ? this.getFileTarget(document, extendsNode) - : vscode.Uri.file(join(dirname(document.uri.fsPath), extendsNode!.value + '.json'))); + vscode.Uri.file(join(workspaceFolderPath, 'node_modules', extendsNode.value + (extendsNode.value.endsWith('.json') ? '' : '.json'))) + ); } private getFilesLinks(document: vscode.TextDocument, root: jsonc.Node) { diff --git a/extensions/typescript-language-features/src/features/typeDefinitions.ts b/extensions/typescript-language-features/src/features/typeDefinitions.ts index 45d89aeaedd..86510f65189 100644 --- a/extensions/typescript-language-features/src/features/typeDefinitions.ts +++ b/extensions/typescript-language-features/src/features/typeDefinitions.ts @@ -10,6 +10,8 @@ import { VersionDependentRegistration } from '../utils/dependentRegistration'; import DefinitionProviderBase from './definitionProviderBase'; export default class TypeScriptTypeDefinitionProvider extends DefinitionProviderBase implements vscode.TypeDefinitionProvider { + public static readonly minVersion = API.v213; + public provideTypeDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise { return this.getSymbolLocations('typeDefinition', document, position, token); } @@ -19,7 +21,7 @@ export function register( selector: vscode.DocumentSelector, client: ITypeScriptServiceClient, ) { - return new VersionDependentRegistration(client, API.v213, () => { + return new VersionDependentRegistration(client, TypeScriptTypeDefinitionProvider.minVersion, () => { return vscode.languages.registerTypeDefinitionProvider(selector, new TypeScriptTypeDefinitionProvider(client)); }); diff --git a/extensions/typescript-language-features/src/features/updatePathsOnRename.ts b/extensions/typescript-language-features/src/features/updatePathsOnRename.ts index 4a0689efac5..c4c2e9ca135 100644 --- a/extensions/typescript-language-features/src/features/updatePathsOnRename.ts +++ b/extensions/typescript-language-features/src/features/updatePathsOnRename.ts @@ -15,7 +15,6 @@ import { VersionDependentRegistration } from '../utils/dependentRegistration'; import { Disposable } from '../utils/dispose'; import * as fileSchemes from '../utils/fileSchemes'; import { isTypeScriptDocument } from '../utils/languageModeIds'; -import { escapeRegExp } from '../utils/regexp'; import * as typeConverters from '../utils/typeConverters'; import FileConfigurationManager from './fileConfigurationManager'; @@ -23,6 +22,17 @@ const localize = nls.loadMessageBundle(); const updateImportsOnFileMoveName = 'updateImportsOnFileMove.enabled'; +function isDirectory(path: string): Promise { + return new Promise((resolve, reject) => { + fs.stat(path, (err, stat) => { + if (err) { + return reject(err); + } + return resolve(stat.isDirectory()); + }); + }); +} + enum UpdateImportsOnFileMoveSetting { Prompt = 'prompt', Always = 'always', @@ -30,6 +40,8 @@ enum UpdateImportsOnFileMoveSetting { } class UpdateImportsOnFileRenameHandler extends Disposable { + public static minVersion = API.v300; + public constructor( private readonly client: ITypeScriptServiceClient, private readonly fileConfigurationManager: FileConfigurationManager, @@ -51,13 +63,10 @@ class UpdateImportsOnFileRenameHandler extends Disposable { oldResource: vscode.Uri, newResource: vscode.Uri, ): Promise { - const targetResource = await this.getTargetResource(newResource); - if (!targetResource) { - return; - } - - const targetFile = this.client.toPath(targetResource); - if (!targetFile) { + // Try to get a js/ts file that is being moved + // For directory moves, this returns a js/ts file under the directory. + const jsTsFileThatIsBeingMoved = await this.getJsTsFileBeingMoved(newResource); + if (!jsTsFileThatIsBeingMoved || !this.client.toPath(jsTsFileThatIsBeingMoved)) { return; } @@ -71,7 +80,7 @@ class UpdateImportsOnFileRenameHandler extends Disposable { return; } - const document = await vscode.workspace.openTextDocument(targetResource); + const document = await vscode.workspace.openTextDocument(jsTsFileThatIsBeingMoved); const config = this.getConfiguration(document); const setting = config.get(updateImportsOnFileMoveName); @@ -83,27 +92,7 @@ class UpdateImportsOnFileRenameHandler extends Disposable { this.client.bufferSyncSupport.closeResource(oldResource); this.client.bufferSyncSupport.openTextDocument(document); - if (this.client.apiVersion.lt(API.v300) && !fs.lstatSync(newResource.fsPath).isDirectory()) { - // Workaround for https://github.com/Microsoft/vscode/issues/52967 - // Never attempt to update import paths if the file does not contain something the looks like an export - try { - const response = await this.client.execute('navtree', { file: newFile }, nulToken); - if (response.type !== 'response' || !response.body) { - return; - } - - const hasExport = (node: Proto.NavigationTree): boolean => { - return !!node.kindModifiers.match(/\bexports?\b/g) || !!(node.childItems && node.childItems.some(hasExport)); - }; - if (!hasExport(response.body)) { - return; - } - } catch { - // noop - } - } - - const edits = await this.getEditsForFileRename(targetFile, document, oldFile, newFile); + const edits = await this.getEditsForFileRename(document, oldFile, newFile); if (!edits || !edits.size) { return; } @@ -204,17 +193,12 @@ class UpdateImportsOnFileRenameHandler extends Disposable { return false; } - private async getTargetResource(resource: vscode.Uri): Promise { + private async getJsTsFileBeingMoved(resource: vscode.Uri): Promise { if (resource.scheme !== fileSchemes.file) { return undefined; } - const isDirectory = fs.lstatSync(resource.fsPath).isDirectory(); - if (isDirectory && this.client.apiVersion.gte(API.v300)) { - return resource; - } - - if (isDirectory && this.client.apiVersion.gte(API.v292)) { + if (await isDirectory(resource.fsPath)) { const files = await vscode.workspace.findFiles({ base: resource.fsPath, pattern: '**/*.{ts,tsx,js,jsx}', @@ -226,17 +210,13 @@ class UpdateImportsOnFileRenameHandler extends Disposable { } private async getEditsForFileRename( - targetResource: string, document: vscode.TextDocument, oldFile: string, newFile: string, ): Promise { - const isDirectoryRename = fs.lstatSync(newFile).isDirectory(); - - const response = await this.client.interuptGetErr(() => { + const response = await this.client.interruptGetErr(() => { this.fileConfigurationManager.setGlobalConfigurationFromDocument(document, nulToken); - const args: Proto.GetEditsForFileRenameRequestArgs & { file: string } = { - file: targetResource, + const args: Proto.GetEditsForFileRenameRequestArgs = { oldFilePath: oldFile, newFilePath: newFile, }; @@ -246,65 +226,7 @@ class UpdateImportsOnFileRenameHandler extends Disposable { return; } - const edits: Proto.FileCodeEdits[] = []; - for (const edit of response.body) { - // Workaround for https://github.com/Microsoft/vscode/issues/52675 - if (this.client.apiVersion.lt(API.v300)) { - if (edit.fileName.match(/[\/\\]node_modules[\/\\]/gi)) { - continue; - } - for (const change of edit.textChanges) { - if (change.newText.match(/\/node_modules\//gi)) { - continue; - } - } - } - - edits.push(await this.fixEdit(edit, isDirectoryRename, oldFile, newFile)); - } - return typeConverters.WorkspaceEdit.fromFileCodeEdits(this.client, edits); - } - - private async fixEdit( - edit: Proto.FileCodeEdits, - isDirectoryRename: boolean, - oldFile: string, - newFile: string, - ): Promise { - if (!isDirectoryRename || this.client.apiVersion.gte(API.v300)) { - return edit; - } - - const document = await vscode.workspace.openTextDocument(edit.fileName); - const oldFileRe = new RegExp('/' + escapeRegExp(path.basename(oldFile)) + '/'); - - // Workaround for https://github.com/Microsoft/TypeScript/issues/24968 - const textChanges = edit.textChanges.map((change): Proto.CodeEdit => { - const existingText = document.getText(typeConverters.Range.fromTextSpan(change)); - const existingMatch = existingText.match(oldFileRe); - if (!existingMatch) { - return change; - } - - const match = new RegExp('/' + escapeRegExp(path.basename(newFile)) + '/(.+)$', 'g').exec(change.newText); - if (!match) { - return change; - } - - return { - newText: change.newText.slice(0, -match[1].length), - start: change.start, - end: { - line: change.end.line, - offset: change.end.offset - match[1].length, - }, - }; - }); - - return { - fileName: edit.fileName, - textChanges, - }; + return typeConverters.WorkspaceEdit.fromFileCodeEdits(this.client, response.body); } } @@ -313,6 +235,6 @@ export function register( fileConfigurationManager: FileConfigurationManager, handles: (uri: vscode.Uri) => Promise, ) { - return new VersionDependentRegistration(client, API.v290, () => + return new VersionDependentRegistration(client, UpdateImportsOnFileRenameHandler.minVersion, () => new UpdateImportsOnFileRenameHandler(client, fileConfigurationManager, handles)); } \ No newline at end of file diff --git a/extensions/typescript-language-features/src/languageProvider.ts b/extensions/typescript-language-features/src/languageProvider.ts index 51f3b91beaf..4210ba2ba20 100644 --- a/extensions/typescript-language-features/src/languageProvider.ts +++ b/extensions/typescript-language-features/src/languageProvider.ts @@ -55,26 +55,30 @@ export default class LanguageProvider extends Disposable { const cachedResponse = new CachedResponse(); - this._register((await import('./features/completions')).register(selector, this.description.id, this.client, this.typingsStatus, this.fileConfigurationManager, this.commandManager, this.onCompletionAccepted)); - this._register((await import('./features/definitions')).register(selector, this.client)); - this._register((await import('./features/directiveCommentCompletions')).register(selector, this.client)); - this._register((await import('./features/documentHighlight')).register(selector, this.client)); - this._register((await import('./features/documentSymbol')).register(selector, this.client, cachedResponse)); - this._register((await import('./features/folding')).register(selector, this.client)); - this._register((await import('./features/formatting')).register(selector, this.description.id, this.client, this.fileConfigurationManager)); - this._register((await import('./features/hover')).register(selector, this.client)); - this._register((await import('./features/implementations')).register(selector, this.client)); - this._register((await import('./features/implementationsCodeLens')).register(selector, this.description.id, this.client, cachedResponse)); - this._register((await import('./features/jsDocCompletions')).register(selector, this.client)); - this._register((await import('./features/organizeImports')).register(selector, this.client, this.commandManager, this.fileConfigurationManager, this.telemetryReporter)); - this._register((await import('./features/quickFix')).register(selector, this.client, this.fileConfigurationManager, this.commandManager, this.client.diagnosticsManager, this.telemetryReporter)); - this._register((await import('./features/refactor')).register(selector, this.client, this.fileConfigurationManager, this.commandManager, this.telemetryReporter)); - this._register((await import('./features/references')).register(selector, this.client)); - this._register((await import('./features/referencesCodeLens')).register(selector, this.description.id, this.client, cachedResponse)); - this._register((await import('./features/rename')).register(selector, this.client)); - this._register((await import('./features/signatureHelp')).register(selector, this.client)); - this._register((await import('./features/tagClosing')).register(selector, this.description.id, this.client)); - this._register((await import('./features/typeDefinitions')).register(selector, this.client)); + await Promise.all([ + import('./features/completions').then(provider => this._register(provider.register(selector, this.description.id, this.client, this.typingsStatus, this.fileConfigurationManager, this.commandManager, this.telemetryReporter, this.onCompletionAccepted))), + import('./features/definitions').then(provider => this._register(provider.register(selector, this.client))), + import('./features/directiveCommentCompletions').then(provider => this._register(provider.register(selector, this.client))), + import('./features/documentHighlight').then(provider => this._register(provider.register(selector, this.client))), + import('./features/documentSymbol').then(provider => this._register(provider.register(selector, this.client, cachedResponse))), + import('./features/folding').then(provider => this._register(provider.register(selector, this.client))), + import('./features/formatting').then(provider => this._register(provider.register(selector, this.description.id, this.client, this.fileConfigurationManager))), + import('./features/hover').then(provider => this._register(provider.register(selector, this.client))), + import('./features/implementations').then(provider => this._register(provider.register(selector, this.client))), + import('./features/implementationsCodeLens').then(provider => this._register(provider.register(selector, this.description.id, this.client, cachedResponse))), + import('./features/jsDocCompletions').then(provider => this._register(provider.register(selector, this.description.id, this.client))), + import('./features/organizeImports').then(provider => this._register(provider.register(selector, this.client, this.commandManager, this.fileConfigurationManager, this.telemetryReporter))), + import('./features/quickFix').then(provider => this._register(provider.register(selector, this.client, this.fileConfigurationManager, this.commandManager, this.client.diagnosticsManager, this.telemetryReporter))), + import('./features/fixAll').then(provider => this._register(provider.register(selector, this.client, this.fileConfigurationManager, this.client.diagnosticsManager))), + import('./features/refactor').then(provider => this._register(provider.register(selector, this.client, this.fileConfigurationManager, this.commandManager, this.telemetryReporter))), + import('./features/references').then(provider => this._register(provider.register(selector, this.client))), + import('./features/referencesCodeLens').then(provider => this._register(provider.register(selector, this.description.id, this.client, cachedResponse))), + import('./features/rename').then(provider => this._register(provider.register(selector, this.client, this.fileConfigurationManager))), + import('./features/smartSelect').then(provider => this._register(provider.register(selector, this.client))), + import('./features/signatureHelp').then(provider => this._register(provider.register(selector, this.client))), + import('./features/tagClosing').then(provider => this._register(provider.register(selector, this.description.id, this.client))), + import('./features/typeDefinitions').then(provider => this._register(provider.register(selector, this.client))), + ]); } private configurationChanged(): void { @@ -89,7 +93,7 @@ export default class LanguageProvider extends Disposable { } const base = basename(resource.fsPath); - return !!base && base === this.description.configFile; + return !!base && (!!this.description.configFilePattern && this.description.configFilePattern.test(base)); } private get id(): string { diff --git a/extensions/typescript-language-features/src/test/cachedResponse.test.ts b/extensions/typescript-language-features/src/test/cachedResponse.test.ts index de1003f284f..919d5d4d03c 100644 --- a/extensions/typescript-language-features/src/test/cachedResponse.test.ts +++ b/extensions/typescript-language-features/src/test/cachedResponse.test.ts @@ -8,7 +8,7 @@ import 'mocha'; import * as vscode from 'vscode'; import * as Proto from '../protocol'; import { CachedResponse } from '../tsServer/cachedResponse'; -import { ServerResponse, CancelledResponse } from '../typescriptService'; +import { ServerResponse } from '../typescriptService'; suite('CachedResponse', () => { test('should cache simple response for same document', async () => { @@ -36,12 +36,12 @@ suite('CachedResponse', () => { const doc = await createTextDocument(); const response = new CachedResponse(); - const cancelledResponder = createEventualResponder(); + const cancelledResponder = createEventualResponder(); const result1 = response.execute(doc, () => cancelledResponder.promise); const result2 = response.execute(doc, respondWith('test-0')); const result3 = response.execute(doc, respondWith('test-1')); - cancelledResponder.resolve(new CancelledResponse('cancelled')); + cancelledResponder.resolve(new ServerResponse.Cancelled('cancelled')); assert.strictEqual((await result1).type, 'cancelled'); assertResult(await result2, 'test-0'); @@ -52,12 +52,12 @@ suite('CachedResponse', () => { const doc = await createTextDocument(); const response = new CachedResponse(); - const cancelledResponder = createEventualResponder(); + const cancelledResponder = createEventualResponder(); const result1 = response.execute(doc, respondWith('test-0')); const result2 = response.execute(doc, () => cancelledResponder.promise); const result3 = response.execute(doc, respondWith('test-1')); - cancelledResponder.resolve(new CancelledResponse('cancelled')); + cancelledResponder.resolve(new ServerResponse.Cancelled('cancelled')); assertResult(await result1, 'test-0'); assertResult(await result2, 'test-0'); @@ -69,8 +69,8 @@ suite('CachedResponse', () => { const doc2 = await createTextDocument(); const response = new CachedResponse(); - const cancelledResponder = createEventualResponder(); - const cancelledResponder2 = createEventualResponder(); + const cancelledResponder = createEventualResponder(); + const cancelledResponder2 = createEventualResponder(); const result1 = response.execute(doc1, () => cancelledResponder.promise); const result2 = response.execute(doc1, respondWith('test-0')); @@ -79,8 +79,8 @@ suite('CachedResponse', () => { const result5 = response.execute(doc2, respondWith('test-2')); const result6 = response.execute(doc1, respondWith('test-3')); - cancelledResponder.resolve(new CancelledResponse('cancelled')); - cancelledResponder2.resolve(new CancelledResponse('cancelled')); + cancelledResponder.resolve(new ServerResponse.Cancelled('cancelled')); + cancelledResponder2.resolve(new ServerResponse.Cancelled('cancelled')); assert.strictEqual((await result1).type, 'cancelled'); assertResult(await result2, 'test-0'); @@ -99,7 +99,7 @@ function createTextDocument() { return vscode.workspace.openTextDocument({ language: 'javascript', content: '' }); } -function assertResult(result: ServerResponse, command: string) { +function assertResult(result: ServerResponse.Response, command: string) { if (result.type === 'response') { assert.strictEqual(result.command, command); } else { diff --git a/extensions/typescript-language-features/src/test/completions.test.ts b/extensions/typescript-language-features/src/test/completions.test.ts index 05a251b0d69..4d1d79dccdb 100644 --- a/extensions/typescript-language-features/src/test/completions.test.ts +++ b/extensions/typescript-language-features/src/test/completions.test.ts @@ -10,35 +10,46 @@ import { disposeAll } from '../utils/dispose'; const testDocumentUri = vscode.Uri.parse('untitled:test.ts'); -const configOverrides: { readonly [key: string]: any } = Object.freeze({ - 'editor.suggestSelection': 'first', - 'typescript.suggest.completeFunctionCalls': false, -}); +type VsCodeConfiguration = { [key: string]: any }; + +async function updateConfig(newConfig: VsCodeConfiguration): Promise { + const oldConfig: VsCodeConfiguration = {}; + const config = vscode.workspace.getConfiguration(undefined, testDocumentUri); + for (const configKey of Object.keys(newConfig)) { + oldConfig[configKey] = config.get(configKey); + await new Promise((resolve, reject) => + config.update(configKey, newConfig[configKey], vscode.ConfigurationTarget.Global) + .then(() => resolve(), reject)); + } + return oldConfig; +} + +namespace Config { + export const suggestSelection = 'editor.suggestSelection'; + export const completeFunctionCalls = 'typescript.suggest.completeFunctionCalls'; +} suite('TypeScript Completions', () => { + const configDefaults: VsCodeConfiguration = Object.freeze({ + [Config.suggestSelection]: 'first', + [Config.completeFunctionCalls]: false, + }); + const _disposables: vscode.Disposable[] = []; let oldConfig: { [key: string]: any } = {}; setup(async () => { await wait(100); - // save off config and update overrides - oldConfig = {}; - const config = vscode.workspace.getConfiguration(undefined, testDocumentUri); - for (const configKey of Object.keys(configOverrides)) { - oldConfig[configKey] = config.get(configKey); - await new Promise((resolve, reject) => config.update(configKey, configOverrides[configKey], vscode.ConfigurationTarget.Global).then(() => resolve(), reject)); - } + // Save off config and apply defaults + oldConfig = await updateConfig(configDefaults); }); teardown(async () => { disposeAll(_disposables); // Restore config - const config = vscode.workspace.getConfiguration(undefined, testDocumentUri); - for (const configKey of Object.keys(oldConfig)) { - await new Promise((resolve, reject) => config.update(configKey, oldConfig[configKey], vscode.ConfigurationTarget.Global).then(() => resolve(), reject)); - } + await updateConfig(oldConfig); return vscode.commands.executeCommand('workbench.action.closeAllEditors'); }); @@ -120,6 +131,9 @@ suite('TypeScript Completions', () => { 'const x = { "hello world2": 1 };', `x["hello world2"]${insert}` )); + + disposeAll(_disposables); + await vscode.commands.executeCommand('workbench.action.closeAllEditors'); } }); @@ -149,7 +163,7 @@ suite('TypeScript Completions', () => { `f('abc.abc$0')` ); - const document = await acceptFirstSuggestion(testDocumentUri, _disposables); + const document = await acceptFirstSuggestion(testDocumentUri, _disposables, { useLineRange: true }); assert.strictEqual( document.getText(), joinLines( @@ -162,7 +176,7 @@ suite('TypeScript Completions', () => { )); }); - test('Accepting a member completion should result in valid code. #58597', async () => { + test.skip('Accepting a member completion should result in valid code. #58597', async () => { await createTestEditor(testDocumentUri, `const abc = 123;`, `ab$0c` @@ -176,17 +190,120 @@ suite('TypeScript Completions', () => { `abc` )); }); + + test('completeFunctionCalls should complete function parameters when at end of word', async () => { + await updateConfig({ + [Config.completeFunctionCalls]: true, + }); + + // Complete with-in word + await createTestEditor(testDocumentUri, + `function abcdef(x, y, z) { }`, + `abcdef$0` + ); + + const document = await acceptFirstSuggestion(testDocumentUri, _disposables); + assert.strictEqual( + document.getText(), + joinLines( + `function abcdef(x, y, z) { }`, + `abcdef(x, y, z)` + )); + }); + + test.skip('completeFunctionCalls should complete function parameters when within word', async () => { + await updateConfig({ + [Config.completeFunctionCalls]: true, + }); + + await createTestEditor(testDocumentUri, + `function abcdef(x, y, z) { }`, + `abcd$0ef` + ); + + const document = await acceptFirstSuggestion(testDocumentUri, _disposables); + assert.strictEqual( + document.getText(), + joinLines( + `function abcdef(x, y, z) { }`, + `abcdef(x, y, z)` + )); + }); + + test('completeFunctionCalls should not complete function parameters at end of word if we are already in something that looks like a function call, #18131', async () => { + await updateConfig({ + [Config.completeFunctionCalls]: true, + }); + + await createTestEditor(testDocumentUri, + `function abcdef(x, y, z) { }`, + `abcdef$0(1, 2, 3)` + ); + + const document = await acceptFirstSuggestion(testDocumentUri, _disposables); + assert.strictEqual( + document.getText(), + joinLines( + `function abcdef(x, y, z) { }`, + `abcdef(1, 2, 3)` + )); + }); + + test.skip('completeFunctionCalls should not complete function parameters within word if we are already in something that looks like a function call, #18131', async () => { + await updateConfig({ + [Config.completeFunctionCalls]: true, + }); + + await createTestEditor(testDocumentUri, + `function abcdef(x, y, z) { }`, + `abcd$0ef(1, 2, 3)` + ); + + const document = await acceptFirstSuggestion(testDocumentUri, _disposables); + assert.strictEqual( + document.getText(), + joinLines( + `function abcdef(x, y, z) { }`, + `abcdef(1, 2, 3)` + )); + }); + + test('should not de-prioritized this.member suggestion, #74164', async () => { + await createTestEditor(testDocumentUri, + `class A {`, + ` private detail = '';`, + ` foo() {`, + ` det$0`, + ` }`, + `}`, + ); + + const document = await acceptFirstSuggestion(testDocumentUri, _disposables); + assert.strictEqual( + document.getText(), + joinLines( + `class A {`, + ` private detail = '';`, + ` foo() {`, + ` this.detail`, + ` }`, + `}`, + )); + }); }); const joinLines = (...args: string[]) => args.join('\n'); const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); -async function acceptFirstSuggestion(uri: vscode.Uri, _disposables: vscode.Disposable[]) { +async function acceptFirstSuggestion(uri: vscode.Uri, _disposables: vscode.Disposable[], options?: { useLineRange?: boolean }) { const didChangeDocument = onChangedDocument(uri, _disposables); - const didSuggest = onDidSuggest(_disposables); + const didSuggest = onDidSuggest(_disposables, options); await vscode.commands.executeCommand('editor.action.triggerSuggest'); await didSuggest; + // TODO: depends on reverting fix for https://github.com/Microsoft/vscode/issues/64257 + // Make sure we have time to resolve the suggestion because `acceptSelectedSuggestion` doesn't + await wait(40); await vscode.commands.executeCommand('acceptSelectedSuggestion'); return await didChangeDocument; } @@ -219,12 +336,14 @@ async function createTestEditor(uri: vscode.Uri, ...lines: string[]) { await activeEditor.insertSnippet(new vscode.SnippetString(joinLines(...lines)), new vscode.Range(0, 0, 1000, 0)); } -function onDidSuggest(disposables: vscode.Disposable[]) { +function onDidSuggest(disposables: vscode.Disposable[], options?: { useLineRange?: boolean }) { return new Promise(resolve => disposables.push(vscode.languages.registerCompletionItemProvider('typescript', new class implements vscode.CompletionItemProvider { provideCompletionItems(doc: vscode.TextDocument, position: vscode.Position): vscode.ProviderResult { // Return a fake item that will come first - const range = new vscode.Range(new vscode.Position(position.line, 0), position); + const range = options && options.useLineRange + ? new vscode.Range(new vscode.Position(position.line, 0), position) + : doc.getWordRangeAtPosition(position); return [{ label: '🦄', insertText: doc.getText(range), diff --git a/extensions/typescript-language-features/src/test/functionCallSnippet.test.ts b/extensions/typescript-language-features/src/test/functionCallSnippet.test.ts index 1fc1fa67980..e053719f3d4 100644 --- a/extensions/typescript-language-features/src/test/functionCallSnippet.test.ts +++ b/extensions/typescript-language-features/src/test/functionCallSnippet.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import 'mocha'; import * as vscode from 'vscode'; -import { snippetForFunctionCall } from "../utils/snippetForFunctionCall"; +import { snippetForFunctionCall } from '../utils/snippetForFunctionCall'; suite('typescript function call snippets', () => { test('Should use label as function name', async () => { @@ -117,4 +117,12 @@ suite('typescript function call snippets', () => { '\\$abc()$0'); }); + test('Should not include object key signature in completion, #66297', async () => { + assert.strictEqual( + snippetForFunctionCall( + { label: 'foobar', }, + [{ "text": "function", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "foobar", "kind": "functionName" }, { "text": "(", "kind": "punctuation" }, { "text": "param", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "{", "kind": "punctuation" }, { "text": "\n", "kind": "lineBreak" }, { "text": " ", "kind": "space" }, { "text": "[", "kind": "punctuation" }, { "text": "key", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "string", "kind": "keyword" }, { "text": "]", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "string", "kind": "keyword" }, { "text": ";", "kind": "punctuation" }, { "text": "\n", "kind": "lineBreak" }, { "text": "}", "kind": "punctuation" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "void", "kind": "keyword" }] + ).snippet.value, + 'foobar(${1:param})$0'); + }); }); diff --git a/extensions/typescript-language-features/src/test/onEnter.test.ts b/extensions/typescript-language-features/src/test/onEnter.test.ts new file mode 100644 index 00000000000..c7d6c3a45dd --- /dev/null +++ b/extensions/typescript-language-features/src/test/onEnter.test.ts @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * 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 'mocha'; +import * as vscode from 'vscode'; +import { CURSOR, withRandomFileEditor } from './testUtils'; + +const onDocumentChange = (doc: vscode.TextDocument): Promise => { + return new Promise(resolve => { + const sub = vscode.workspace.onDidChangeTextDocument(e => { + if (e.document !== doc) { + return; + } + sub.dispose(); + resolve(e.document); + }); + }); +}; + +const type = async (document: vscode.TextDocument, text: string): Promise => { + const onChange = onDocumentChange(document); + await vscode.commands.executeCommand('type', { text }); + await onChange; + return document; +}; + +suite('OnEnter', () => { + test('should indent after if block with braces', () => { + return withRandomFileEditor(`if (true) {${CURSOR}`, 'js', async (_editor, document) => { + await type(document, '\nx'); + assert.strictEqual(document.getText(), `if (true) {\n x`); + }); + }); + + test('should indent within empty object literal', () => { + return withRandomFileEditor(`({${CURSOR}})`, 'js', async (_editor, document) => { + await type(document, '\nx'); + assert.strictEqual(document.getText(), `({\n x\n})`); + }); + }); + + test('should indent after simple jsx tag with attributes', () => { + return withRandomFileEditor(`const a =
    ${CURSOR}`, 'jsx', async (_editor, document) => { + await type(document, '\nx'); + assert.strictEqual(document.getText(), `const a =
    \n x`); + }); + }); + + test('should indent after simple jsx tag with attributes', () => { + return withRandomFileEditor(`const a =
    ${CURSOR}`, 'jsx', async (_editor, document) => { + await type(document, '\nx'); + assert.strictEqual(document.getText(), `const a =
    \n x`); + }); + }); +}); \ No newline at end of file diff --git a/extensions/typescript-language-features/src/test/server.test.ts b/extensions/typescript-language-features/src/test/server.test.ts new file mode 100644 index 00000000000..651967fc12c --- /dev/null +++ b/extensions/typescript-language-features/src/test/server.test.ts @@ -0,0 +1,76 @@ +/*--------------------------------------------------------------------------------------------- + * 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 'mocha'; +import * as stream from 'stream'; +import { PipeRequestCanceller, TsServerProcess, ProcessBasedTsServer } from '../tsServer/server'; +import { nulToken } from '../utils/cancellation'; +import Logger from '../utils/logger'; +import TelemetryReporter from '../utils/telemetry'; +import Tracer from '../utils/tracer'; +import * as Proto from '../protocol'; + + +const NoopTelemetryReporter = new class implements TelemetryReporter { + logTelemetry(): void { /* noop */ } + dispose(): void { /* noop */ } +}; + +class FakeServerProcess implements TsServerProcess { + private readonly _out: stream.PassThrough; + + private readonly writeListeners = new Set<(data: Buffer) => void>(); + public stdout: stream.PassThrough; + + constructor() { + this._out = new stream.PassThrough(); + this.stdout = this._out; + } + + public write(data: Proto.Request) { + const listeners = Array.from(this.writeListeners); + this.writeListeners.clear(); + + setImmediate(() => { + for (const listener of listeners) { + listener(Buffer.from(JSON.stringify(data), 'utf8')); + } + const body = Buffer.from(JSON.stringify({ 'seq': data.seq, 'type': 'response', 'command': data.command, 'request_seq': data.seq, 'success': true }), 'utf8'); + this._out.write(Buffer.from(`Content-Length: ${body.length}\r\n\r\n${body}`, 'utf8')); + }); + } + + + on(_name: any, _handler: any) { /* noop */ } + + kill(): void { /* noop */ } + + public onWrite(): Promise { + return new Promise((resolve) => { + this.writeListeners.add((data) => { + resolve(JSON.parse(data.toString())); + }); + }); + } +} + +suite('Server', () => { + const tracer = new Tracer(new Logger()); + + test('should send requests with increasing sequence numbers', async () => { + const process = new FakeServerProcess(); + const server = new ProcessBasedTsServer('semantic', process, undefined, new PipeRequestCanceller('semantic', undefined, tracer), undefined!, NoopTelemetryReporter, tracer); + + const onWrite1 = process.onWrite(); + server.executeImpl('geterr', {}, { isAsync: false, token: nulToken, expectsResult: true }); + assert.strictEqual((await onWrite1).seq, 0); + + const onWrite2 = process.onWrite(); + server.executeImpl('geterr', {}, { isAsync: false, token: nulToken, expectsResult: true }); + assert.strictEqual((await onWrite2).seq, 1); + }); +}); + diff --git a/extensions/typescript-language-features/src/test/testUtils.ts b/extensions/typescript-language-features/src/test/testUtils.ts new file mode 100644 index 00000000000..d8efdc3f9c4 --- /dev/null +++ b/extensions/typescript-language-features/src/test/testUtils.ts @@ -0,0 +1,68 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import * as fs from 'fs'; +import * as os from 'os'; +import { join } from 'path'; + +function rndName() { + return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); +} + +export function createRandomFile(contents = '', fileExtension = 'txt'): Thenable { + return new Promise((resolve, reject) => { + const tmpFile = join(os.tmpdir(), rndName() + '.' + fileExtension); + fs.writeFile(tmpFile, contents, (error) => { + if (error) { + return reject(error); + } + + resolve(vscode.Uri.file(tmpFile)); + }); + }); +} + + +export function deleteFile(file: vscode.Uri): Thenable { + return new Promise((resolve, reject) => { + fs.unlink(file.fsPath, (err) => { + if (err) { + reject(err); + } else { + resolve(true); + } + }); + }); +} + +export const CURSOR = '$$CURSOR$$'; + +export function withRandomFileEditor( + contents: string, + fileExtension: string, + run: (editor: vscode.TextEditor, doc: vscode.TextDocument) => Thenable +): Thenable { + const cursorIndex = contents.indexOf(CURSOR); + return createRandomFile(contents.replace(CURSOR, ''), fileExtension).then(file => { + return vscode.workspace.openTextDocument(file).then(doc => { + return vscode.window.showTextDocument(doc).then((editor) => { + if (cursorIndex >= 0) { + const pos = doc.positionAt(cursorIndex); + editor.selection = new vscode.Selection(pos, pos); + } + return run(editor, doc).then(_ => { + if (doc.isDirty) { + return doc.save().then(() => { + return deleteFile(file); + }); + } else { + return deleteFile(file); + } + }); + }); + }); + }); +} \ No newline at end of file diff --git a/extensions/typescript-language-features/src/tsServer/cachedResponse.ts b/extensions/typescript-language-features/src/tsServer/cachedResponse.ts index ea8414cf8a5..2fb9b542281 100644 --- a/extensions/typescript-language-features/src/tsServer/cachedResponse.ts +++ b/extensions/typescript-language-features/src/tsServer/cachedResponse.ts @@ -7,13 +7,13 @@ import * as vscode from 'vscode'; import * as Proto from '../protocol'; import { ServerResponse } from '../typescriptService'; -type Resolve = () => Promise>; +type Resolve = () => Promise>; /** * Caches a class of TS Server request based on document. */ export class CachedResponse { - private response?: Promise>; + private response?: Promise>; private version: number = -1; private document: string = ''; @@ -25,7 +25,7 @@ export class CachedResponse { public execute( document: vscode.TextDocument, resolve: Resolve - ): Promise> { + ): Promise> { if (this.response && this.matches(document)) { // Chain so that on cancellation we fall back to the next resolve return this.response = this.response.then(result => result.type === 'cancelled' ? resolve() : result); @@ -40,7 +40,7 @@ export class CachedResponse { private async reset( document: vscode.TextDocument, resolve: Resolve - ): Promise> { + ): Promise> { this.version = document.version; this.document = document.uri.toString(); return this.response = resolve(); diff --git a/extensions/typescript-language-features/src/tsServer/callbackMap.ts b/extensions/typescript-language-features/src/tsServer/callbackMap.ts index 5c187ec1485..7f96de57159 100644 --- a/extensions/typescript-language-features/src/tsServer/callbackMap.ts +++ b/extensions/typescript-language-features/src/tsServer/callbackMap.ts @@ -4,21 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import * as Proto from '../protocol'; -import { CancelledResponse, ServerResponse } from '../typescriptService'; +import { ServerResponse } from '../typescriptService'; export interface CallbackItem { readonly onSuccess: (value: R) => void; - readonly onError: (err: any) => void; + readonly onError: (err: Error) => void; readonly startTime: number; readonly isAsync: boolean; } export class CallbackMap { - private readonly _callbacks = new Map | undefined>>(); - private readonly _asyncCallbacks = new Map | undefined>>(); + private readonly _callbacks = new Map | undefined>>(); + private readonly _asyncCallbacks = new Map | undefined>>(); public destroy(cause: string): void { - const cancellation = new CancelledResponse(cause); + const cancellation = new ServerResponse.Cancelled(cause); for (const callback of this._callbacks.values()) { callback.onSuccess(cancellation); } @@ -29,7 +29,7 @@ export class CallbackMap { this._asyncCallbacks.clear(); } - public add(seq: number, callback: CallbackItem | undefined>, isAsync: boolean) { + public add(seq: number, callback: CallbackItem | undefined>, isAsync: boolean) { if (isAsync) { this._asyncCallbacks.set(seq, callback); } else { @@ -37,7 +37,7 @@ export class CallbackMap { } } - public fetch(seq: number): CallbackItem | undefined> | undefined { + public fetch(seq: number): CallbackItem | undefined> | undefined { const callback = this._callbacks.get(seq) || this._asyncCallbacks.get(seq); this.delete(seq); return callback; diff --git a/extensions/typescript-language-features/src/tsServer/server.ts b/extensions/typescript-language-features/src/tsServer/server.ts index e3c1dbff0af..f10b02abf8e 100644 --- a/extensions/typescript-language-features/src/tsServer/server.ts +++ b/extensions/typescript-language-features/src/tsServer/server.ts @@ -3,188 +3,99 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as cp from 'child_process'; import * as fs from 'fs'; -import * as path from 'path'; +import * as stream from 'stream'; import * as vscode from 'vscode'; import * as Proto from '../protocol'; -import { CancelledResponse, NoContentResponse } from '../typescriptService'; -import API from '../utils/api'; -import { TsServerLogLevel, TypeScriptServiceConfiguration } from '../utils/configuration'; +import { ServerResponse, TypeScriptRequests } from '../typescriptService'; import { Disposable } from '../utils/dispose'; -import * as electron from '../utils/electron'; -import LogDirectoryProvider from '../utils/logDirectoryProvider'; -import Logger from '../utils/logger'; -import { TypeScriptPluginPathsProvider } from '../utils/pluginPathsProvider'; -import { PluginManager } from '../utils/plugins'; import TelemetryReporter from '../utils/telemetry'; import Tracer from '../utils/tracer'; -import { TypeScriptVersion, TypeScriptVersionProvider } from '../utils/versionProvider'; +import { TypeScriptVersion } from '../utils/versionProvider'; import { Reader } from '../utils/wireProtocol'; import { CallbackMap } from './callbackMap'; import { RequestItem, RequestQueue, RequestQueueingType } from './requestQueue'; +import { TypeScriptServerError } from './serverError'; -export class TypeScriptServerSpawner { +export interface OngoingRequestCanceller { + tryCancelOngoingRequest(seq: number): boolean; +} + +export class PipeRequestCanceller implements OngoingRequestCanceller { public constructor( - private readonly _versionProvider: TypeScriptVersionProvider, - private readonly _logDirectoryProvider: LogDirectoryProvider, - private readonly _pluginPathsProvider: TypeScriptPluginPathsProvider, - private readonly _logger: Logger, - private readonly _telemetryReporter: TelemetryReporter, + private readonly _serverId: string, + private readonly _cancellationPipeName: string | undefined, private readonly _tracer: Tracer, ) { } - public spawn( - version: TypeScriptVersion, - configuration: TypeScriptServiceConfiguration, - pluginManager: PluginManager - ): TypeScriptServer { - const apiVersion = version.version || API.defaultVersion; - - const { args, cancellationPipeName, tsServerLogFile } = this.getTsServerArgs(configuration, version, pluginManager); - - if (TypeScriptServerSpawner.isLoggingEnabled(apiVersion, configuration)) { - if (tsServerLogFile) { - this._logger.info(`TSServer log file: ${tsServerLogFile}`); - } else { - this._logger.error('Could not create TSServer log directory'); - } + public tryCancelOngoingRequest(seq: number): boolean { + if (!this._cancellationPipeName) { + return false; } - - this._logger.info('Forking TSServer'); - const childProcess = electron.fork(version.tsServerPath, args, this.getForkOptions()); - this._logger.info('Started TSServer'); - - return new TypeScriptServer(childProcess, tsServerLogFile, cancellationPipeName, this._logger, this._telemetryReporter, this._tracer); - } - - private getForkOptions() { - const debugPort = TypeScriptServerSpawner.getDebugPort(); - const tsServerForkOptions: electron.ForkOptions = { - execArgv: debugPort ? [`--inspect=${debugPort}`] : [], - }; - return tsServerForkOptions; - } - - private getTsServerArgs( - configuration: TypeScriptServiceConfiguration, - currentVersion: TypeScriptVersion, - pluginManager: PluginManager, - ): { args: string[], cancellationPipeName: string | undefined, tsServerLogFile: string | undefined } { - const args: string[] = []; - let cancellationPipeName: string | undefined; - let tsServerLogFile: string | undefined; - - const apiVersion = currentVersion.version || API.defaultVersion; - - if (apiVersion.gte(API.v206)) { - if (apiVersion.gte(API.v250)) { - args.push('--useInferredProjectPerProjectRoot'); - } else { - args.push('--useSingleInferredProject'); - } - - if (configuration.disableAutomaticTypeAcquisition) { - args.push('--disableAutomaticTypingAcquisition'); - } + this._tracer.logTrace(this._serverId, `TypeScript Server: trying to cancel ongoing request with sequence number ${seq}`); + try { + fs.writeFileSync(this._cancellationPipeName + seq, ''); + } catch { + // noop } - - if (apiVersion.gte(API.v208)) { - args.push('--enableTelemetry'); - } - - if (apiVersion.gte(API.v222)) { - cancellationPipeName = electron.getTempFile('tscancellation'); - args.push('--cancellationPipeName', cancellationPipeName + '*'); - } - - if (TypeScriptServerSpawner.isLoggingEnabled(apiVersion, configuration)) { - const logDir = this._logDirectoryProvider.getNewLogDirectory(); - if (logDir) { - tsServerLogFile = path.join(logDir, `tsserver.log`); - args.push('--logVerbosity', TsServerLogLevel.toString(configuration.tsServerLogLevel)); - args.push('--logFile', tsServerLogFile); - } - } - - if (apiVersion.gte(API.v230)) { - const pluginPaths = this._pluginPathsProvider.getPluginPaths(); - - if (pluginManager.plugins.length) { - args.push('--globalPlugins', pluginManager.plugins.map(x => x.name).join(',')); - - const isUsingBundledTypeScriptVersion = currentVersion.path === this._versionProvider.defaultVersion.path; - for (const plugin of pluginManager.plugins) { - if (isUsingBundledTypeScriptVersion || plugin.enableForWorkspaceTypeScriptVersions) { - pluginPaths.push(plugin.path); - } - } - } - - if (pluginPaths.length !== 0) { - args.push('--pluginProbeLocations', pluginPaths.join(',')); - } - } - - if (apiVersion.gte(API.v234)) { - if (configuration.npmLocation) { - args.push('--npmLocation', `"${configuration.npmLocation}"`); - } - } - - if (apiVersion.gte(API.v260)) { - args.push('--locale', TypeScriptServerSpawner.getTsLocale(configuration)); - } - - if (apiVersion.gte(API.v291)) { - args.push('--noGetErrOnBackgroundUpdate'); - } - - return { args, cancellationPipeName, tsServerLogFile }; - } - - private static getDebugPort(): number | undefined { - const value = process.env['TSS_DEBUG']; - if (value) { - const port = parseInt(value); - if (!isNaN(port)) { - return port; - } - } - return undefined; - } - - private static isLoggingEnabled(apiVersion: API, configuration: TypeScriptServiceConfiguration) { - return apiVersion.gte(API.v222) && - configuration.tsServerLogLevel !== TsServerLogLevel.Off; - } - - private static getTsLocale(configuration: TypeScriptServiceConfiguration): string { - return configuration.locale - ? configuration.locale - : vscode.env.language; + return true; } } -export class TypeScriptServer extends Disposable { +export interface ITypeScriptServer { + readonly onEvent: vscode.Event; + readonly onExit: vscode.Event; + readonly onError: vscode.Event; + readonly onReaderError: vscode.Event; + + readonly tsServerLogFile: string | undefined; + + kill(): void; + + executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean }): undefined; + executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise>; + executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise> | undefined; + + dispose(): void; +} + +export interface TsServerProcess { + readonly stdout: stream.Readable; + write(serverRequest: Proto.Request): void; + + on(name: 'exit', handler: (code: number | null) => void): void; + on(name: 'error', handler: (error: Error) => void): void; + + kill(): void; +} + +export class ProcessBasedTsServer extends Disposable implements ITypeScriptServer { private readonly _reader: Reader; private readonly _requestQueue = new RequestQueue(); private readonly _callbacks = new CallbackMap(); private readonly _pendingResponses = new Set(); constructor( - private readonly _childProcess: cp.ChildProcess, + private readonly _serverId: string, + private readonly _process: TsServerProcess, private readonly _tsServerLogFile: string | undefined, - private readonly _cancellationPipeName: string | undefined, - private readonly _logger: Logger, + private readonly _requestCanceller: OngoingRequestCanceller, + private readonly _version: TypeScriptVersion, private readonly _telemetryReporter: TelemetryReporter, private readonly _tracer: Tracer, ) { super(); - this._reader = this._register(new Reader(this._childProcess.stdout)); + this._reader = this._register(new Reader(this._process.stdout!)); this._reader.onData(msg => this.dispatchMessage(msg)); - this._childProcess.on('exit', code => this.handleExit(code)); - this._childProcess.on('error', error => this.handleError(error)); + + this._process.on('exit', code => { + this._onExit.fire(code); + this._callbacks.destroy('server exited'); + }); + this._process.on('error', error => { + this._onError.fire(error); + this._callbacks.destroy('server errored'); + }); } private readonly _onEvent = this._register(new vscode.EventEmitter()); @@ -200,8 +111,8 @@ export class TypeScriptServer extends Disposable { public get tsServerLogFile() { return this._tsServerLogFile; } - public write(serverRequest: Proto.Request) { - this._childProcess.stdin.write(JSON.stringify(serverRequest) + '\r\n', 'utf8'); + private write(serverRequest: Proto.Request) { + this._process.write(serverRequest); } public dispose() { @@ -211,17 +122,7 @@ export class TypeScriptServer extends Disposable { } public kill() { - this._childProcess.kill(); - } - - private handleExit(error: any) { - this._onExit.fire(error); - this._callbacks.destroy('server exited'); - } - - private handleError(error: any) { - this._onError.fire(error); - this._callbacks.destroy('server errored'); + this._process.kill(); } private dispatchMessage(message: Proto.Message) { @@ -237,11 +138,11 @@ export class TypeScriptServer extends Disposable { const seq = (event as Proto.RequestCompletedEvent).body.request_seq; const p = this._callbacks.fetch(seq); if (p) { - this._tracer.traceRequestCompleted('requestCompleted', seq, p.startTime); + this._tracer.traceRequestCompleted(this._serverId, 'requestCompleted', seq, p.startTime); p.onSuccess(undefined); } } else { - this._tracer.traceEvent(event); + this._tracer.traceEvent(this._serverId, event); this._onEvent.fire(event); } break; @@ -257,26 +158,20 @@ export class TypeScriptServer extends Disposable { private tryCancelRequest(seq: number, command: string): boolean { try { if (this._requestQueue.tryDeletePendingRequest(seq)) { - this._tracer.logTrace(`TypeScript Server: canceled request with sequence number ${seq}`); + this.logTrace(`Canceled request with sequence number ${seq}`); return true; } - if (this._cancellationPipeName) { - this._tracer.logTrace(`TypeScript Server: trying to cancel ongoing request with sequence number ${seq}`); - try { - fs.writeFileSync(this._cancellationPipeName + seq, ''); - } catch { - // noop - } + if (this._requestCanceller.tryCancelOngoingRequest(seq)) { return true; } - this._tracer.logTrace(`TypeScript Server: tried to cancel request with sequence number ${seq}. But request got already delivered.`); + this.logTrace(`Tried to cancel request with sequence number ${seq}. But request got already delivered.`); return false; } finally { const callback = this.fetchCallback(seq); if (callback) { - callback.onSuccess(new CancelledResponse(`Cancelled request ${seq} - ${command}`)); + callback.onSuccess(new ServerResponse.Cancelled(`Cancelled request ${seq} - ${command}`)); } } } @@ -287,89 +182,70 @@ export class TypeScriptServer extends Disposable { return; } - this._tracer.traceResponse(response, callback.startTime); + this._tracer.traceResponse(this._serverId, response, callback.startTime); if (response.success) { callback.onSuccess(response); } else if (response.message === 'No content available.') { // Special case where response itself is successful but there is not any data to return. - callback.onSuccess(new NoContentResponse()); + callback.onSuccess(ServerResponse.NoContent); } else { - callback.onError(response); + callback.onError(TypeScriptServerError.create(this._serverId, this._version, response)); } } - public executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise { + public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean }): undefined; + public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise>; + public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise> | undefined { const request = this._requestQueue.createRequest(command, args); const requestInfo: RequestItem = { request, expectsResponse: executeInfo.expectsResult, isAsync: executeInfo.isAsync, - queueingType: getQueueingType(command, executeInfo.lowPriority) + queueingType: ProcessBasedTsServer.getQueueingType(command, executeInfo.lowPriority) }; - let result: Promise; + let result: Promise> | undefined; if (executeInfo.expectsResult) { - let wasCancelled = false; - result = new Promise((resolve, reject) => { + result = new Promise>((resolve, reject) => { this._callbacks.add(request.seq, { onSuccess: resolve, onError: reject, startTime: Date.now(), isAsync: executeInfo.isAsync }, executeInfo.isAsync); if (executeInfo.token) { executeInfo.token.onCancellationRequested(() => { - wasCancelled = true; this.tryCancelRequest(request.seq, command); }); } - }).catch((err: any) => { - if (!wasCancelled) { - this._logger.error(`'${command}' request failed with error.`, err); - const properties = this.parseErrorText(err && err.message, command); - /* __GDPR__ - "languageServiceErrorResponse" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "message" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "stack" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "errortext" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, - "${include}": [ - "${TypeScriptCommonProperties}" - ] - } - */ - this._telemetryReporter.logTelemetry('languageServiceErrorResponse', properties); + }).catch((err: Error) => { + if (err instanceof TypeScriptServerError) { + if (!executeInfo.token || !executeInfo.token.isCancellationRequested) { + /* __GDPR__ + "languageServiceErrorResponse" : { + "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "message" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, + "stack" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, + "errortext" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }, + "${include}": [ + "${TypeScriptCommonProperties}" + ] + } + */ + this._telemetryReporter.logTelemetry('languageServiceErrorResponse', { + command: err.serverCommand, + message: err.serverMessage || '', + stack: err.serverStack || '', + errortext: err.serverErrorText || '', + }); + } } + throw err; }); - } else { - result = Promise.resolve(null); } + this._requestQueue.enqueue(requestInfo); this.sendNextRequests(); return result; } - /** - * Given a `errorText` from a tsserver request indicating failure in handling a request, - * prepares a payload for telemetry-logging. - */ - private parseErrorText(errorText: string | undefined, command: string) { - const properties: ObjectMap = Object.create(null); - properties['command'] = command; - if (errorText) { - properties['errorText'] = errorText; - - const errorPrefix = 'Error processing request. '; - if (errorText.startsWith(errorPrefix)) { - const prefixFreeErrorText = errorText.substr(errorPrefix.length); - const newlineIndex = prefixFreeErrorText.indexOf('\n'); - if (newlineIndex >= 0) { - // Newline expected between message and stack. - properties['message'] = prefixFreeErrorText.substring(0, newlineIndex); - properties['stack'] = prefixFreeErrorText.substring(newlineIndex + 1); - } - } - } - return properties; - } - private sendNextRequests(): void { while (this._pendingResponses.size === 0 && this._requestQueue.length > 0) { const item = this._requestQueue.dequeue(); @@ -381,7 +257,7 @@ export class TypeScriptServer extends Disposable { private sendRequest(requestItem: RequestItem): void { const serverRequest = requestItem.request; - this._tracer.traceRequest(serverRequest, requestItem.expectsResponse, this._requestQueue.length); + this._tracer.traceRequest(this._serverId, serverRequest, requestItem.expectsResponse, this._requestQueue.length); if (requestItem.expectsResponse && !requestItem.isAsync) { this._pendingResponses.add(requestItem.request.seq); @@ -406,17 +282,115 @@ export class TypeScriptServer extends Disposable { this._pendingResponses.delete(seq); return callback; } -} -const fenceCommands = new Set(['change', 'close', 'open']); - -function getQueueingType( - command: string, - lowPriority?: boolean -): RequestQueueingType { - if (fenceCommands.has(command)) { - return RequestQueueingType.Fence; + private logTrace(message: string) { + this._tracer.logTrace(this._serverId, message); + } + + private static readonly fenceCommands = new Set(['change', 'close', 'open', 'updateOpen']); + + private static getQueueingType( + command: string, + lowPriority?: boolean + ): RequestQueueingType { + if (ProcessBasedTsServer.fenceCommands.has(command)) { + return RequestQueueingType.Fence; + } + return lowPriority ? RequestQueueingType.LowPriority : RequestQueueingType.Normal; } - return lowPriority ? RequestQueueingType.LowPriority : RequestQueueingType.Normal; } + +export class SyntaxRoutingTsServer extends Disposable implements ITypeScriptServer { + public constructor( + private readonly syntaxServer: ITypeScriptServer, + private readonly semanticServer: ITypeScriptServer, + ) { + super(); + + this._register(syntaxServer.onEvent(e => this._onEvent.fire(e))); + this._register(semanticServer.onEvent(e => this._onEvent.fire(e))); + + this._register(semanticServer.onExit(e => { + this._onExit.fire(e); + this.syntaxServer.kill(); + })); + this._register(semanticServer.onError(e => this._onError.fire(e))); + } + + private readonly _onEvent = this._register(new vscode.EventEmitter()); + public readonly onEvent = this._onEvent.event; + + private readonly _onExit = this._register(new vscode.EventEmitter()); + public readonly onExit = this._onExit.event; + + private readonly _onError = this._register(new vscode.EventEmitter()); + public readonly onError = this._onError.event; + + public get onReaderError() { return this.semanticServer.onReaderError; } + + public get tsServerLogFile() { return this.semanticServer.tsServerLogFile; } + + public kill(): void { + this.syntaxServer.kill(); + this.semanticServer.kill(); + } + + private static readonly syntaxCommands = new Set([ + 'navtree', + 'getOutliningSpans', + 'jsxClosingTag', + 'selectionRange', + 'format', + 'formatonkey', + 'docCommentTemplate', + ]); + private static readonly sharedCommands = new Set([ + 'change', + 'close', + 'open', + 'updateOpen', + 'configure', + 'configurePlugin', + ]); + + public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean }): undefined; + public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise>; + public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise> | undefined { + if (SyntaxRoutingTsServer.syntaxCommands.has(command)) { + return this.syntaxServer.executeImpl(command, args, executeInfo); + } else if (SyntaxRoutingTsServer.sharedCommands.has(command)) { + // Dispatch to both server but only return from syntax one + + // Also make sure we never cancel requests to just one server + let hasCompletedSyntax = false; + let hasCompletedSemantic = false; + let token: vscode.CancellationToken | undefined = undefined; + if (executeInfo.token) { + const source = new vscode.CancellationTokenSource(); + executeInfo.token.onCancellationRequested(() => { + if (hasCompletedSyntax && !hasCompletedSemantic || hasCompletedSemantic && !hasCompletedSyntax) { + // Don't cancel. + // One of the servers completed this request so we don't want to leave the other + // in a different state + return; + } + source.cancel(); + }); + token = source.token; + } + + const semanticRequest = this.semanticServer.executeImpl(command, args, { ...executeInfo, token }); + if (semanticRequest) { + semanticRequest.finally(() => { hasCompletedSemantic = true; }); + } + const syntaxRequest = this.syntaxServer.executeImpl(command, args, { ...executeInfo, token }); + if (syntaxRequest) { + syntaxRequest.finally(() => { hasCompletedSyntax = true; }); + } + return syntaxRequest; + } else { + return this.semanticServer.executeImpl(command, args, executeInfo); + } + } +} diff --git a/extensions/typescript-language-features/src/tsServer/serverError.ts b/extensions/typescript-language-features/src/tsServer/serverError.ts new file mode 100644 index 00000000000..cb5cb8035f1 --- /dev/null +++ b/extensions/typescript-language-features/src/tsServer/serverError.ts @@ -0,0 +1,66 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as Proto from '../protocol'; +import { escapeRegExp } from '../utils/regexp'; +import { TypeScriptVersion } from '../utils/versionProvider'; + +export class TypeScriptServerError extends Error { + public static create( + serverId: string, + version: TypeScriptVersion, + response: Proto.Response + ): TypeScriptServerError { + const parsedResult = TypeScriptServerError.parseErrorText(version, response); + return new TypeScriptServerError(serverId, version, response, parsedResult ? parsedResult.message : undefined, parsedResult ? parsedResult.stack : undefined); + } + + private constructor( + serverId: string, + version: TypeScriptVersion, + private readonly response: Proto.Response, + public readonly serverMessage: string | undefined, + public readonly serverStack: string | undefined + ) { + super(`<${serverId}> TypeScript Server Error (${version.versionString})\n${serverMessage}\n${serverStack}`); + } + + public get serverErrorText() { return this.response.message; } + + public get serverCommand() { return this.response.command; } + + /** + * Given a `errorText` from a tsserver request indicating failure in handling a request, + * prepares a payload for telemetry-logging. + */ + private static parseErrorText(version: TypeScriptVersion, response: Proto.Response) { + const errorText = response.message; + if (errorText) { + const errorPrefix = 'Error processing request. '; + if (errorText.startsWith(errorPrefix)) { + const prefixFreeErrorText = errorText.substr(errorPrefix.length); + const newlineIndex = prefixFreeErrorText.indexOf('\n'); + if (newlineIndex >= 0) { + // Newline expected between message and stack. + return { + message: prefixFreeErrorText.substring(0, newlineIndex), + stack: TypeScriptServerError.normalizeMessageStack(version, prefixFreeErrorText.substring(newlineIndex + 1)) + }; + } + } + } + return undefined; + } + + /** + * Try to replace full TS Server paths with 'tsserver.js' so that we don't have to post process the data as much + */ + private static normalizeMessageStack(version: TypeScriptVersion, message: string | undefined) { + if (!message) { + return ''; + } + return message.replace(new RegExp(`${escapeRegExp(version.path)}[/\\\\]tsserver.js:`, 'gi'), 'tsserver.js:'); + } +} diff --git a/extensions/typescript-language-features/src/tsServer/spawner.ts b/extensions/typescript-language-features/src/tsServer/spawner.ts new file mode 100644 index 00000000000..599abe32ca1 --- /dev/null +++ b/extensions/typescript-language-features/src/tsServer/spawner.ts @@ -0,0 +1,229 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as child_process from 'child_process'; +import * as path from 'path'; +import * as stream from 'stream'; +import * as vscode from 'vscode'; +import * as Proto from '../protocol'; +import API from '../utils/api'; +import { TsServerLogLevel, TypeScriptServiceConfiguration } from '../utils/configuration'; +import * as electron from '../utils/electron'; +import LogDirectoryProvider from '../utils/logDirectoryProvider'; +import Logger from '../utils/logger'; +import { TypeScriptPluginPathsProvider } from '../utils/pluginPathsProvider'; +import { PluginManager } from '../utils/plugins'; +import TelemetryReporter from '../utils/telemetry'; +import Tracer from '../utils/tracer'; +import { TypeScriptVersion, TypeScriptVersionProvider } from '../utils/versionProvider'; +import { ITypeScriptServer, PipeRequestCanceller, ProcessBasedTsServer, SyntaxRoutingTsServer, TsServerProcess } from './server'; + +type ServerKind = 'main' | 'syntax' | 'semantic'; + +export class TypeScriptServerSpawner { + public constructor( + private readonly _versionProvider: TypeScriptVersionProvider, + private readonly _logDirectoryProvider: LogDirectoryProvider, + private readonly _pluginPathsProvider: TypeScriptPluginPathsProvider, + private readonly _logger: Logger, + private readonly _telemetryReporter: TelemetryReporter, + private readonly _tracer: Tracer, + ) { } + + public spawn( + version: TypeScriptVersion, + configuration: TypeScriptServiceConfiguration, + pluginManager: PluginManager + ): ITypeScriptServer { + if (this.shouldUseSeparateSyntaxServer(version, configuration)) { + const syntaxServer = this.spawnTsServer('syntax', version, configuration, pluginManager); + const semanticServer = this.spawnTsServer('semantic', version, configuration, pluginManager); + return new SyntaxRoutingTsServer(syntaxServer, semanticServer); + } + + return this.spawnTsServer('main', version, configuration, pluginManager); + } + + private shouldUseSeparateSyntaxServer( + version: TypeScriptVersion, + configuration: TypeScriptServiceConfiguration, + ): boolean { + return configuration.useSeparateSyntaxServer && !!version.apiVersion && version.apiVersion.gte(API.v340); + } + + private spawnTsServer( + kind: ServerKind, + version: TypeScriptVersion, + configuration: TypeScriptServiceConfiguration, + pluginManager: PluginManager, + ): ITypeScriptServer { + const apiVersion = version.apiVersion || API.defaultVersion; + + const { args, cancellationPipeName, tsServerLogFile } = this.getTsServerArgs(kind, configuration, version, apiVersion, pluginManager); + + if (TypeScriptServerSpawner.isLoggingEnabled(apiVersion, configuration)) { + if (tsServerLogFile) { + this._logger.info(`<${kind}> Log file: ${tsServerLogFile}`); + } else { + this._logger.error(`<${kind}> Could not create log directory`); + } + } + + this._logger.info(`<${kind}> Forking...`); + const childProcess = electron.fork(version.tsServerPath, args, this.getForkOptions(kind)); + this._logger.info(`<${kind}> Starting...`); + + return new ProcessBasedTsServer( + kind, + new ChildServerProcess(childProcess), + tsServerLogFile, + new PipeRequestCanceller(kind, cancellationPipeName, this._tracer), + version, + this._telemetryReporter, + this._tracer); + } + + private getForkOptions(kind: ServerKind) { + const debugPort = TypeScriptServerSpawner.getDebugPort(kind); + const tsServerForkOptions: electron.ForkOptions = { + execArgv: debugPort ? [`--inspect=${debugPort}`] : [], + }; + return tsServerForkOptions; + } + + private getTsServerArgs( + kind: ServerKind, + configuration: TypeScriptServiceConfiguration, + currentVersion: TypeScriptVersion, + apiVersion: API, + pluginManager: PluginManager, + ): { args: string[], cancellationPipeName: string | undefined, tsServerLogFile: string | undefined } { + const args: string[] = []; + let cancellationPipeName: string | undefined; + let tsServerLogFile: string | undefined; + + if (kind === 'syntax') { + args.push('--syntaxOnly'); + } + + if (apiVersion.gte(API.v206)) { + if (apiVersion.gte(API.v250)) { + args.push('--useInferredProjectPerProjectRoot'); + } else { + args.push('--useSingleInferredProject'); + } + + if (configuration.disableAutomaticTypeAcquisition || kind === 'syntax') { + args.push('--disableAutomaticTypingAcquisition'); + } + } + + if (apiVersion.gte(API.v208) && kind !== 'syntax') { + args.push('--enableTelemetry'); + } + + if (apiVersion.gte(API.v222)) { + cancellationPipeName = electron.getTempFile('tscancellation'); + args.push('--cancellationPipeName', cancellationPipeName + '*'); + } + + if (TypeScriptServerSpawner.isLoggingEnabled(apiVersion, configuration)) { + const logDir = this._logDirectoryProvider.getNewLogDirectory(); + if (logDir) { + tsServerLogFile = path.join(logDir, `tsserver.log`); + args.push('--logVerbosity', TsServerLogLevel.toString(configuration.tsServerLogLevel)); + args.push('--logFile', tsServerLogFile); + } + } + + if (apiVersion.gte(API.v230)) { + const pluginPaths = this._pluginPathsProvider.getPluginPaths(); + + if (pluginManager.plugins.length) { + args.push('--globalPlugins', pluginManager.plugins.map(x => x.name).join(',')); + + const isUsingBundledTypeScriptVersion = currentVersion.path === this._versionProvider.defaultVersion.path; + for (const plugin of pluginManager.plugins) { + if (isUsingBundledTypeScriptVersion || plugin.enableForWorkspaceTypeScriptVersions) { + pluginPaths.push(plugin.path); + } + } + } + + if (pluginPaths.length !== 0) { + args.push('--pluginProbeLocations', pluginPaths.join(',')); + } + } + + if (apiVersion.gte(API.v234)) { + if (configuration.npmLocation) { + args.push('--npmLocation', `"${configuration.npmLocation}"`); + } + } + + if (apiVersion.gte(API.v260)) { + args.push('--locale', TypeScriptServerSpawner.getTsLocale(configuration)); + } + + if (apiVersion.gte(API.v291)) { + args.push('--noGetErrOnBackgroundUpdate'); + } + + if (apiVersion.gte(API.v345)) { + args.push('--validateDefaultNpmLocation'); + } + + return { args, cancellationPipeName, tsServerLogFile }; + } + + private static getDebugPort(kind: ServerKind): number | undefined { + if (kind === 'syntax') { + // We typically only want to debug the main semantic server + return undefined; + } + const value = process.env['TSS_DEBUG']; + if (value) { + const port = parseInt(value); + if (!isNaN(port)) { + return port; + } + } + return undefined; + } + + private static isLoggingEnabled(apiVersion: API, configuration: TypeScriptServiceConfiguration) { + return apiVersion.gte(API.v222) && + configuration.tsServerLogLevel !== TsServerLogLevel.Off; + } + + private static getTsLocale(configuration: TypeScriptServiceConfiguration): string { + return configuration.locale + ? configuration.locale + : vscode.env.language; + } +} + +class ChildServerProcess implements TsServerProcess { + + public constructor( + private readonly _process: child_process.ChildProcess, + ) { } + + get stdout(): stream.Readable { return this._process.stdout!; } + + write(serverRequest: Proto.Request): void { + this._process.stdin!.write(JSON.stringify(serverRequest) + '\r\n', 'utf8'); + } + + on(name: 'exit', handler: (code: number | null) => void): void; + on(name: 'error', handler: (error: Error) => void): void; + on(name: any, handler: any) { + this._process.on(name, handler); + } + + kill(): void { + this._process.kill(); + } +} \ No newline at end of file diff --git a/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts b/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts index 9c76d5e50ab..2571d395a5f 100644 --- a/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts +++ b/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts @@ -24,11 +24,13 @@ import { PluginManager } from './utils/plugins'; import * as typeConverters from './utils/typeConverters'; import TypingsStatus, { AtaProgressReporter } from './utils/typingsStatus'; import VersionStatus from './utils/versionStatus'; +import { flatten } from './utils/arrays'; // Style check diagnostics that can be reported as warnings const styleCheckDiagnostics = [ 6133, // variable is declared but never used 6138, // property is declared but its value is never read + 6192, // All imports are unused 7027, // unreachable code detected 7028, // unused label 7029, // fall through case in switch @@ -55,7 +57,6 @@ export default class TypeScriptServiceClientHost extends Disposable { ) { super(); const handleProjectCreateOrDelete = () => { - this.client.executeWithoutWaitingForResponse('reloadProjects', null); this.triggerAllDiagnostics(); }; const handleProjectChange = () => { @@ -68,7 +69,7 @@ export default class TypeScriptServiceClientHost extends Disposable { configFileWatcher.onDidDelete(handleProjectCreateOrDelete, this, this._disposables); configFileWatcher.onDidChange(handleProjectChange, this, this._disposables); - const allModeIds = this.getAllModeIds(descriptions); + const allModeIds = this.getAllModeIds(descriptions, pluginManager); this.client = this._register(new TypeScriptServiceClient( workspaceState, version => this.versionStatus.onDidChangeTypeScriptVersion(version), @@ -138,11 +139,11 @@ export default class TypeScriptServiceClientHost extends Disposable { this.configurationChanged(); } - private getAllModeIds(descriptions: LanguageDescription[]) { - const allModeIds: string[] = []; - for (const description of descriptions) { - allModeIds.push(...description.modeIds); - } + private getAllModeIds(descriptions: LanguageDescription[], pluginManager: PluginManager) { + const allModeIds = flatten([ + ...descriptions.map(x => x.modeIds), + ...pluginManager.plugins.map(x => x.languages) + ]); return allModeIds; } @@ -218,47 +219,17 @@ export default class TypeScriptServiceClientHost extends Disposable { return; } - (this.findLanguage(this.client.toResource(body.configFile))).then(language => { + this.findLanguage(this.client.toResource(body.configFile)).then(language => { if (!language) { return; } - if (body.diagnostics.length === 0) { - language.configFileDiagnosticsReceived(this.client.toResource(body.configFile), []); - } else if (body.diagnostics.length >= 1) { - vscode.workspace.openTextDocument(vscode.Uri.file(body.configFile)).then((document) => { - let curly: [number, number, number] | undefined = undefined; - let nonCurly: [number, number, number] | undefined = undefined; - let diagnostic: vscode.Diagnostic; - for (let index = 0; index < document.lineCount; index++) { - const line = document.lineAt(index); - const text = line.text; - const firstNonWhitespaceCharacterIndex = line.firstNonWhitespaceCharacterIndex; - if (firstNonWhitespaceCharacterIndex < text.length) { - if (text.charAt(firstNonWhitespaceCharacterIndex) === '{') { - curly = [index, firstNonWhitespaceCharacterIndex, firstNonWhitespaceCharacterIndex + 1]; - break; - } else { - const matches = /\s*([^\s]*)(?:\s*|$)/.exec(text.substr(firstNonWhitespaceCharacterIndex)); - if (matches && matches.length >= 1) { - nonCurly = [index, firstNonWhitespaceCharacterIndex, firstNonWhitespaceCharacterIndex + matches[1].length]; - } - } - } - } - const match = curly || nonCurly; - if (match) { - diagnostic = new vscode.Diagnostic(new vscode.Range(match[0], match[1], match[0], match[2]), body.diagnostics[0].text); - } else { - diagnostic = new vscode.Diagnostic(new vscode.Range(0, 0, 0, 0), body.diagnostics[0].text); - } - if (diagnostic) { - diagnostic.source = language.diagnosticSource; - language.configFileDiagnosticsReceived(this.client.toResource(body.configFile), [diagnostic]); - } - }, _error => { - language.configFileDiagnosticsReceived(this.client.toResource(body.configFile), [new vscode.Diagnostic(new vscode.Range(0, 0, 0, 0), body.diagnostics[0].text)]); - }); - } + + language.configFileDiagnosticsReceived(this.client.toResource(body.configFile), body.diagnostics.map(tsDiag => { + const range = tsDiag.start && tsDiag.end ? typeConverters.Range.fromTextSpan(tsDiag) : new vscode.Range(0, 0, 0, 1); + const diagnostic = new vscode.Diagnostic(range, body.diagnostics[0].text, this.getDiagnosticSeverity(tsDiag)); + diagnostic.source = language.diagnosticSource; + return diagnostic; + })); }); } @@ -272,8 +243,7 @@ export default class TypeScriptServiceClientHost extends Disposable { private tsDiagnosticToVsDiagnostic(diagnostic: Proto.Diagnostic, source: string): vscode.Diagnostic & { reportUnnecessary: any } { const { start, end, text } = diagnostic; const range = new vscode.Range(typeConverters.Position.fromLocation(start), typeConverters.Position.fromLocation(end)); - const converted = new vscode.Diagnostic(range, text); - converted.severity = this.getDiagnosticSeverity(diagnostic); + const converted = new vscode.Diagnostic(range, text, this.getDiagnosticSeverity(diagnostic)); converted.source = diagnostic.source || source; if (diagnostic.code) { converted.code = diagnostic.code; diff --git a/extensions/typescript-language-features/src/typescriptService.ts b/extensions/typescript-language-features/src/typescriptService.ts index 874cb020a94..ba396ad2fd2 100644 --- a/extensions/typescript-language-features/src/typescriptService.ts +++ b/extensions/typescript-language-features/src/typescriptService.ts @@ -11,21 +11,22 @@ import { TypeScriptServiceConfiguration } from './utils/configuration'; import Logger from './utils/logger'; import { PluginManager } from './utils/plugins'; -export class CancelledResponse { - public readonly type: 'cancelled' = 'cancelled'; +export namespace ServerResponse { - constructor( - public readonly reason: string - ) { } + export class Cancelled { + public readonly type = 'cancelled'; + + constructor( + public readonly reason: string + ) { } + } + + export const NoContent = new class { readonly type = 'noContent'; }; + + export type Response = T | Cancelled | typeof NoContent; } -export class NoContentResponse { - public readonly type: 'noContent' = 'noContent'; -} - -export type ServerResponse = T | CancelledResponse | NoContentResponse; - -interface TypeScriptRequestTypes { +interface StandardTsServerRequests { 'applyCodeActionCommand': [Proto.ApplyCodeActionCommandRequestArgs, Proto.ApplyCodeActionCommandResponse]; 'completionEntryDetails': [Proto.CompletionDetailsRequestArgs, Proto.CompletionDetailsResponse]; 'completionInfo': [Proto.CompletionsRequestArgs, Proto.CompletionInfoResponse]; @@ -38,7 +39,7 @@ interface TypeScriptRequestTypes { 'format': [Proto.FormatRequestArgs, Proto.FormatResponse]; 'formatonkey': [Proto.FormatOnKeyRequestArgs, Proto.FormatResponse]; 'getApplicableRefactors': [Proto.GetApplicableRefactorsRequestArgs, Proto.GetApplicableRefactorsResponse]; - 'getCodeFixes': [Proto.CodeFixRequestArgs, Proto.GetCodeFixesResponse]; + 'getCodeFixes': [Proto.CodeFixRequestArgs, Proto.CodeFixResponse]; 'getCombinedCodeFix': [Proto.GetCombinedCodeFixRequestArgs, Proto.GetCombinedCodeFixResponse]; 'getEditsForFileRename': [Proto.GetEditsForFileRenameRequestArgs, Proto.GetEditsForFileRenameResponse]; 'getEditsForRefactor': [Proto.GetEditsForRefactorRequestArgs, Proto.GetEditsForRefactorResponse]; @@ -48,16 +49,36 @@ interface TypeScriptRequestTypes { 'jsxClosingTag': [Proto.JsxClosingTagRequestArgs, Proto.JsxClosingTagResponse]; 'navto': [Proto.NavtoRequestArgs, Proto.NavtoResponse]; 'navtree': [Proto.FileRequestArgs, Proto.NavTreeResponse]; - 'occurrences': [Proto.FileLocationRequestArgs, Proto.OccurrencesResponse]; 'organizeImports': [Proto.OrganizeImportsRequestArgs, Proto.OrganizeImportsResponse]; 'projectInfo': [Proto.ProjectInfoRequestArgs, Proto.ProjectInfoResponse]; 'quickinfo': [Proto.FileLocationRequestArgs, Proto.QuickInfoResponse]; 'references': [Proto.FileLocationRequestArgs, Proto.ReferencesResponse]; 'rename': [Proto.RenameRequestArgs, Proto.RenameResponse]; + 'selectionRange': [Proto.SelectionRangeRequestArgs, Proto.SelectionRangeResponse]; 'signatureHelp': [Proto.SignatureHelpRequestArgs, Proto.SignatureHelpResponse]; 'typeDefinition': [Proto.FileLocationRequestArgs, Proto.TypeDefinitionResponse]; } +interface NoResponseTsServerRequests { + 'open': [Proto.OpenRequestArgs, null]; + 'close': [Proto.FileRequestArgs]; + 'change': [Proto.ChangeRequestArgs, null]; + 'updateOpen': [Proto.UpdateOpenRequestArgs, null]; + 'compilerOptionsForInferredProjects': [Proto.SetCompilerOptionsForInferredProjectsArgs, null]; + 'reloadProjects': [null, null]; + 'configurePlugin': [Proto.ConfigurePluginRequest, Proto.ConfigurePluginResponse]; +} + +interface AsyncTsServerRequests { + 'geterr': [Proto.GeterrRequestArgs, Proto.Response]; +} + +export type TypeScriptRequests = StandardTsServerRequests & NoResponseTsServerRequests & AsyncTsServerRequests; + +export type ExecConfig = { + lowPriority?: boolean; +}; + export interface ITypeScriptServiceClient { /** * Convert a resource (VS Code) to a normalized path (TypeScript). @@ -99,23 +120,22 @@ export interface ITypeScriptServiceClient { readonly logger: Logger; readonly bufferSyncSupport: BufferSyncSupport; - execute( + execute( command: K, - args: TypeScriptRequestTypes[K][0], + args: StandardTsServerRequests[K][0], token: vscode.CancellationToken, - lowPriority?: boolean - ): Promise>; + config?: ExecConfig + ): Promise>; - executeWithoutWaitingForResponse(command: 'open', args: Proto.OpenRequestArgs): void; - executeWithoutWaitingForResponse(command: 'close', args: Proto.FileRequestArgs): void; - executeWithoutWaitingForResponse(command: 'change', args: Proto.ChangeRequestArgs): void; - executeWithoutWaitingForResponse(command: 'compilerOptionsForInferredProjects', args: Proto.SetCompilerOptionsForInferredProjectsArgs): void; - executeWithoutWaitingForResponse(command: 'reloadProjects', args: null): void; + executeWithoutWaitingForResponse( + command: K, + args: NoResponseTsServerRequests[K][0] + ): void; - executeAsync(command: 'geterr', args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise; + executeAsync(command: 'geterr', args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise>; /** * Cancel on going geterr requests and re-queue them after `f` has been evaluated. */ - interuptGetErr(f: () => R): R; + interruptGetErr(f: () => R): R; } \ No newline at end of file diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index 9e02bbedc81..996478d6c22 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -10,8 +10,8 @@ import * as nls from 'vscode-nls'; import BufferSyncSupport from './features/bufferSyncSupport'; import { DiagnosticKind, DiagnosticsManager } from './features/diagnostics'; import * as Proto from './protocol'; -import { TypeScriptServer, TypeScriptServerSpawner } from './tsServer/server'; -import { ITypeScriptServiceClient } from './typescriptService'; +import { ITypeScriptServer } from './tsServer/server'; +import { ITypeScriptServiceClient, ServerResponse, TypeScriptRequests, ExecConfig } from './typescriptService'; import API from './utils/api'; import { TsServerLogLevel, TypeScriptServiceConfiguration } from './utils/configuration'; import { Disposable } from './utils/dispose'; @@ -20,11 +20,12 @@ import LogDirectoryProvider from './utils/logDirectoryProvider'; import Logger from './utils/logger'; import { TypeScriptPluginPathsProvider } from './utils/pluginPathsProvider'; import { PluginManager } from './utils/plugins'; -import TelemetryReporter from './utils/telemetry'; +import TelemetryReporter, { VSCodeTelemetryReporter } from './utils/telemetry'; import Tracer from './utils/tracer'; import { inferredProjectConfig } from './utils/tsconfig'; import { TypeScriptVersionPicker } from './utils/versionPicker'; import { TypeScriptVersion, TypeScriptVersionProvider } from './utils/versionProvider'; +import { TypeScriptServerSpawner } from './tsServer/spawner'; const localize = nls.loadMessageBundle(); @@ -34,6 +35,43 @@ export interface TsDiagnostics { readonly diagnostics: Proto.Diagnostic[]; } +namespace ServerState { + export const enum Type { + None, + Running, + Errored + } + + export const None = new class { readonly type = Type.None; }; + + export class Running { + readonly type = Type.Running; + constructor( + public readonly server: ITypeScriptServer, + + /** + * API version obtained from the version picker after checking the corresponding path exists. + */ + public readonly apiVersion: API, + + /** + * Version reported by currently-running tsserver. + */ + public tsserverVersion: string | undefined, + public langaugeServiceEnabled: boolean, + ) { } + } + + export class Errored { + readonly type = Type.Errored; + constructor( + public readonly error: Error, + ) { } + } + + export type State = typeof None | Running | Errored; +} + export default class TypeScriptServiceClient extends Disposable implements ITypeScriptServiceClient { private static readonly WALK_THROUGH_SNIPPET_SCHEME_COLON = `${fileSchemes.walkThroughSnippet}:`; @@ -49,23 +87,13 @@ export default class TypeScriptServiceClient extends Disposable implements IType public readonly logger: Logger = new Logger(); private readonly typescriptServerSpawner: TypeScriptServerSpawner; - private forkedTsServer: TypeScriptServer | null; - private lastError: Error | null; + private serverState: ServerState.State = ServerState.None; private lastStart: number; private numberRestarts: number; private isRestarting: boolean = false; private loadingIndicator = new ServerInitializingIndicator(); public readonly telemetryReporter: TelemetryReporter; - /** - * API version obtained from the version picker after checking the corresponding path exists. - */ - private _apiVersion: API; - - /** - * Version reported by currently-running tsserver. - */ - private _tsserverVersion: string | undefined; public readonly bufferSyncSupport: BufferSyncSupport; public readonly diagnosticsManager: DiagnosticsManager; @@ -87,8 +115,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType }); this._onReady!.promise = p; - this.forkedTsServer = null; - this.lastError = null; this.numberRestarts = 0; this._configuration = TypeScriptServiceConfiguration.loadFromWorkspace(); @@ -96,8 +122,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType this.pluginPathsProvider = new TypeScriptPluginPathsProvider(this._configuration); this.versionPicker = new TypeScriptVersionPicker(this.versionProvider, this.workspaceState); - this._apiVersion = API.defaultVersion; - this._tsserverVersion = undefined; this.tracer = new Tracer(this.logger); this.bufferSyncSupport = new BufferSyncSupport(this, allModeIds); @@ -116,7 +140,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType this.pluginPathsProvider.updateConfiguration(this._configuration); this.tracer.updateConfiguration(); - if (this.forkedTsServer) { + if (this.serverState.type === ServerState.Type.Running) { if (this._configuration.checkJs !== oldConfiguration.checkJs || this._configuration.experimentalDecorators !== oldConfiguration.experimentalDecorators ) { @@ -129,13 +153,24 @@ export default class TypeScriptServiceClient extends Disposable implements IType } }, this, this._disposables); - this.telemetryReporter = this._register(new TelemetryReporter(() => this._tsserverVersion || this._apiVersion.versionString)); + this.telemetryReporter = this._register(new VSCodeTelemetryReporter(() => { + if (this.serverState.type === ServerState.Type.Running) { + if (this.serverState.tsserverVersion) { + return this.serverState.tsserverVersion; + } + } + return this.apiVersion.versionString; + })); this.typescriptServerSpawner = new TypeScriptServerSpawner(this.versionProvider, this.logDirectoryProvider, this.pluginPathsProvider, this.logger, this.telemetryReporter, this.tracer); this._register(this.pluginManager.onDidUpdateConfig(update => { this.configurePlugin(update.pluginId, update.config); })); + + this._register(this.pluginManager.onDidChangePlugins(() => { + this.restartTsServer(); + })); } public get configuration() { @@ -147,22 +182,21 @@ export default class TypeScriptServiceClient extends Disposable implements IType this.bufferSyncSupport.dispose(); - if (this.forkedTsServer) { - this.forkedTsServer.kill(); + if (this.serverState.type === ServerState.Type.Running) { + this.serverState.server.kill(); } this.loadingIndicator.reset(); } public restartTsServer(): void { - if (this.forkedTsServer) { + if (this.serverState.type === ServerState.Type.Running) { this.info('Killing TS Server'); this.isRestarting = true; - this.forkedTsServer.kill(); - this.resetClientVersion(); + this.serverState.server.kill(); } - this.forkedTsServer = this.startService(true); + this.serverState = this.startService(true); } private readonly _onTsServerStarted = this._register(new vscode.EventEmitter()); @@ -193,7 +227,10 @@ export default class TypeScriptServiceClient extends Disposable implements IType public readonly onSurveyReady = this._onSurveyReady.event; public get apiVersion(): API { - return this._apiVersion; + if (this.serverState.type === ServerState.Type.Running) { + return this.serverState.apiVersion; + } + return API.defaultVersion; } public onReady(f: () => void): Promise { @@ -212,30 +249,30 @@ export default class TypeScriptServiceClient extends Disposable implements IType this.telemetryReporter.logTelemetry(eventName, properties); } - private service(): TypeScriptServer | null { - if (this.forkedTsServer) { - return this.forkedTsServer; + private service(): ServerState.Running { + if (this.serverState.type === ServerState.Type.Running) { + return this.serverState; } - if (this.lastError) { - throw this.lastError; + if (this.serverState.type === ServerState.Type.Errored) { + throw this.serverState.error; } - this.startService(); - if (this.forkedTsServer) { - return this.forkedTsServer; + const newState = this.startService(); + if (newState.type === ServerState.Type.Running) { + return newState; } throw new Error('Could not create TS service'); } public ensureServiceStarted() { - if (!this.forkedTsServer) { + if (this.serverState.type !== ServerState.Type.Running) { this.startService(); } } private token: number = 0; - private startService(resendModels: boolean = false): TypeScriptServer | null { + private startService(resendModels: boolean = false): ServerState.State { if (this.isDisposed) { - return null; + return ServerState.None; } let currentVersion = this.versionPicker.currentVersion; @@ -248,13 +285,13 @@ export default class TypeScriptServiceClient extends Disposable implements IType currentVersion = this.versionPicker.currentVersion; } - this._apiVersion = this.versionPicker.currentVersion.version || API.defaultVersion; + const apiVersion = this.versionPicker.currentVersion.apiVersion || API.defaultVersion; this.onDidChangeTypeScriptVersion(currentVersion); - this.lastError = null; let mytoken = ++this.token; const handle = this.typescriptServerSpawner.spawn(currentVersion, this.configuration, this.pluginManager); + this.serverState = new ServerState.Running(handle, apiVersion, undefined, true); this.lastStart = Date.now(); handle.onError((err: Error) => { @@ -267,7 +304,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType vscode.window.showErrorMessage(localize('serverExitedWithError', 'TypeScript language server exited with error. Error message is: {0}', err.message || err.name)); } - this.lastError = err; + this.serverState = new ServerState.Errored(err); this.error('TSServer errored with error.', err); if (handle.tsServerLogFile) { this.error(`TSServer log file: ${handle.tsServerLogFile}`); @@ -282,7 +319,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType */ this.logTelemetry('tsserver.error'); this.serviceExited(false); - this.resetClientVersion(); }); handle.onExit((code: any) => { @@ -317,16 +353,15 @@ export default class TypeScriptServiceClient extends Disposable implements IType handle.onEvent(event => this.dispatchEvent(event)); this._onReady!.resolve(); - this.forkedTsServer = handle; - this._onTsServerStarted.fire(currentVersion.version); + this._onTsServerStarted.fire(currentVersion.apiVersion); - if (this._apiVersion.gte(API.v300)) { + if (apiVersion.gte(API.v300)) { this.loadingIndicator.startedLoadingProject(undefined /* projectName */); } this.serviceStarted(resendModels); - return handle; + return this.serverState; } public onVersionStatusClicked(): Thenable { @@ -372,7 +407,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType return false; } - if (!this.forkedTsServer || !this.forkedTsServer.tsServerLogFile) { + if (this.serverState.type !== ServerState.Type.Running || !this.serverState.server.tsServerLogFile) { vscode.window.showWarningMessage(localize( 'typescript.openTsServerLog.noLogFile', 'TS Server has not started logging.')); @@ -380,7 +415,15 @@ export default class TypeScriptServiceClient extends Disposable implements IType } try { - await vscode.commands.executeCommand('revealFileInOS', vscode.Uri.file(this.forkedTsServer.tsServerLogFile)); + const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(this.serverState.server.tsServerLogFile)); + await vscode.window.showTextDocument(doc); + return true; + } catch { + // noop + } + + try { + await vscode.commands.executeCommand('revealFileInOS', vscode.Uri.file(this.serverState.server.tsServerLogFile)); return true; } catch { vscode.window.showWarningMessage(localize( @@ -393,6 +436,10 @@ export default class TypeScriptServiceClient extends Disposable implements IType private serviceStarted(resendModels: boolean): void { const configureOptions: Proto.ConfigureRequestArguments = { hostInfo: 'vscode', + preferences: { + providePrefixAndSuffixTextForRename: true, + allowRenameOfImportPath: true, + } }; this.executeWithoutWaitingForResponse('configure', configureOptions); this.setCompilerOptionsForInferredProjects(this._configuration); @@ -437,10 +484,8 @@ export default class TypeScriptServiceClient extends Disposable implements IType id: MessageAction; } - this.forkedTsServer = null; - if (!restart) { - this.resetClientVersion(); - } else { + this.serverState = ServerState.None; + if (restart) { const diff = Date.now() - this.lastStart; this.numberRestarts++; let startService = true; @@ -464,7 +509,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType } */ this.logTelemetry('serviceExited'); - this.resetClientVersion(); } else if (diff < 60 * 1000 /* 1 Minutes */) { this.lastStart = Date.now(); prompt = vscode.window.showWarningMessage( @@ -490,7 +534,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType } public normalizedPath(resource: vscode.Uri): string | undefined { - if (this._apiVersion.gte(API.v213)) { + if (this.apiVersion.gte(API.v213)) { if (resource.scheme === fileSchemes.walkThroughSnippet || resource.scheme === fileSchemes.untitled) { const dirName = path.dirname(resource.path); const fileName = this.inMemoryResourcePrefix + path.basename(resource.path); @@ -524,11 +568,11 @@ export default class TypeScriptServiceClient extends Disposable implements IType } private get inMemoryResourcePrefix(): string { - return this._apiVersion.gte(API.v270) ? '^' : ''; + return this.apiVersion.gte(API.v270) ? '^' : ''; } public toResource(filepath: string): vscode.Uri { - if (this._apiVersion.gte(API.v213)) { + if (this.apiVersion.gte(API.v213)) { if (filepath.startsWith(TypeScriptServiceClient.WALK_THROUGH_SNIPPET_SCHEME_COLON) || (filepath.startsWith(fileSchemes.untitled + ':')) ) { let resource = vscode.Uri.parse(filepath); @@ -563,16 +607,16 @@ export default class TypeScriptServiceClient extends Disposable implements IType return undefined; } - public execute(command: string, args: any, token: vscode.CancellationToken, lowPriority?: boolean): Promise { + public execute(command: keyof TypeScriptRequests, args: any, token: vscode.CancellationToken, config?: ExecConfig): Promise> { return this.executeImpl(command, args, { isAsync: false, token, expectsResult: true, - lowPriority + lowPriority: config ? config.lowPriority : undefined }); } - public executeWithoutWaitingForResponse(command: string, args: any): void { + public executeWithoutWaitingForResponse(command: keyof TypeScriptRequests, args: any): void { this.executeImpl(command, args, { isAsync: false, token: undefined, @@ -580,7 +624,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType }); } - public executeAsync(command: string, args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise { + public executeAsync(command: keyof TypeScriptRequests, args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise> { return this.executeImpl(command, args, { isAsync: true, token, @@ -588,15 +632,15 @@ export default class TypeScriptServiceClient extends Disposable implements IType }); } - private executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise { - const server = this.service(); - if (!server) { - return Promise.reject(new Error('Could not load TS Server')); - } - return server.executeImpl(command, args, executeInfo); + private executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean }): undefined; + private executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise>; + private executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise> | undefined { + this.bufferSyncSupport.beforeCommand(command); + const runningServerState = this.service(); + return runningServerState.server.executeImpl(command, args, executeInfo); } - public interuptGetErr(f: () => R): R { + public interruptGetErr(f: () => R): R { return this.bufferSyncSupport.interuptGetErr(f); } @@ -605,8 +649,8 @@ export default class TypeScriptServiceClient extends Disposable implements IType case 'syntaxDiag': case 'semanticDiag': case 'suggestionDiag': - // This event also roughly signals that the global project has been loaded successfully - this.loadingIndicator.finishedLoadingProject(undefined /* projectName */); + // This event also roughly signals that projects have been loaded successfully (since the TS server is synchronous) + this.loadingIndicator.reset(); const diagnosticEvent = event as Proto.DiagnosticEvent; if (diagnosticEvent.body && diagnosticEvent.body.diagnostics) { @@ -623,14 +667,23 @@ export default class TypeScriptServiceClient extends Disposable implements IType break; case 'telemetry': - const telemetryData = (event as Proto.TelemetryEvent).body; - this.dispatchTelemetryEvent(telemetryData); - break; - + { + const body = (event as Proto.TelemetryEvent).body; + this.dispatchTelemetryEvent(body); + break; + } case 'projectLanguageServiceState': - this._onProjectLanguageServiceStateChanged.fire((event as Proto.ProjectLanguageServiceStateEvent).body); - break; - + { + const body = (event as Proto.ProjectLanguageServiceStateEvent).body!; + if (this.serverState.type === ServerState.Type.Running) { + this.serverState = { + ...this.serverState, + langaugeServiceEnabled: body.languageServiceEnabled, + }; + } + this._onProjectLanguageServiceStateChanged.fire(body); + break; + } case 'projectsUpdatedInBackground': const body = (event as Proto.ProjectsUpdatedInBackgroundEvent).body; const resources = body.openFiles.map(vscode.Uri.file); @@ -694,7 +747,12 @@ export default class TypeScriptServiceClient extends Disposable implements IType break; } if (telemetryData.telemetryEventName === 'projectInfo') { - this._tsserverVersion = properties['version']; + if (this.serverState.type === ServerState.Type.Running) { + this.serverState = { + ...this.serverState, + tsserverVersion: properties['version'] + }; + } } /* __GDPR__ @@ -711,13 +769,8 @@ export default class TypeScriptServiceClient extends Disposable implements IType this.logTelemetry(telemetryData.telemetryEventName, properties); } - private resetClientVersion() { - this._apiVersion = API.defaultVersion; - this._tsserverVersion = undefined; - } - private configurePlugin(pluginName: string, configuration: {}): any { - if (this._apiVersion.gte(API.v314)) { + if (this.apiVersion.gte(API.v314)) { this.executeWithoutWaitingForResponse('configurePlugin', { pluginName, configuration }); } } diff --git a/extensions/typescript-language-features/src/typings/ref.d.ts b/extensions/typescript-language-features/src/typings/ref.d.ts index 954bab971e3..c9849d48e08 100644 --- a/extensions/typescript-language-features/src/typings/ref.d.ts +++ b/extensions/typescript-language-features/src/typings/ref.d.ts @@ -5,4 +5,3 @@ /// /// -/// diff --git a/extensions/typescript-language-features/src/utils/api.ts b/extensions/typescript-language-features/src/utils/api.ts index 3071afbc4dd..01f3ac6e6a5 100644 --- a/extensions/typescript-language-features/src/utils/api.ts +++ b/extensions/typescript-language-features/src/utils/api.ts @@ -34,6 +34,10 @@ export default class API { public static readonly v314 = API.fromSimpleString('3.1.4'); public static readonly v320 = API.fromSimpleString('3.2.0'); public static readonly v330 = API.fromSimpleString('3.3.0'); + public static readonly v333 = API.fromSimpleString('3.3.3'); + public static readonly v340 = API.fromSimpleString('3.4.0'); + public static readonly v345 = API.fromSimpleString('3.4.5'); + public static readonly v350 = API.fromSimpleString('3.5.0'); public static fromVersionString(versionString: string): API { diff --git a/extensions/typescript-language-features/src/utils/arrays.ts b/extensions/typescript-language-features/src/utils/arrays.ts index bf403c3afeb..f9435fe9b20 100644 --- a/extensions/typescript-language-features/src/utils/arrays.ts +++ b/extensions/typescript-language-features/src/utils/arrays.ts @@ -2,20 +2,23 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export function equals(one: ReadonlyArray, other: ReadonlyArray, itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean { - if (one.length !== other.length) { + +export const empty = Object.freeze([]); + +export function equals( + a: ReadonlyArray, + b: ReadonlyArray, + itemEquals: (a: T, b: T) => boolean = (a, b) => a === b +): boolean { + if (a === b) { + return true; + } + if (a.length !== b.length) { return false; } - - for (let i = 0, len = one.length; i < len; i++) { - if (!itemEquals(one[i], other[i])) { - return false; - } - } - - return true; + return a.every((x, i) => itemEquals(x, b[i])); } export function flatten(arr: ReadonlyArray[]): T[] { - return ([] as T[]).concat.apply([], arr); + return Array.prototype.concat.apply([], arr); } \ No newline at end of file diff --git a/extensions/typescript-language-features/src/utils/configuration.ts b/extensions/typescript-language-features/src/utils/configuration.ts index 3babc53c91b..f0e602e810a 100644 --- a/extensions/typescript-language-features/src/utils/configuration.ts +++ b/extensions/typescript-language-features/src/utils/configuration.ts @@ -54,6 +54,7 @@ export class TypeScriptServiceConfiguration { public readonly checkJs: boolean; public readonly experimentalDecorators: boolean; public readonly disableAutomaticTypeAcquisition: boolean; + public readonly useSeparateSyntaxServer: boolean; public static loadFromWorkspace(): TypeScriptServiceConfiguration { return new TypeScriptServiceConfiguration(); @@ -71,6 +72,7 @@ export class TypeScriptServiceConfiguration { this.checkJs = TypeScriptServiceConfiguration.readCheckJs(configuration); this.experimentalDecorators = TypeScriptServiceConfiguration.readExperimentalDecorators(configuration); this.disableAutomaticTypeAcquisition = TypeScriptServiceConfiguration.readDisableAutomaticTypeAcquisition(configuration); + this.useSeparateSyntaxServer = TypeScriptServiceConfiguration.readUseSeparateSyntaxServer(configuration); } public isEqualTo(other: TypeScriptServiceConfiguration): boolean { @@ -82,7 +84,8 @@ export class TypeScriptServiceConfiguration { && this.checkJs === other.checkJs && this.experimentalDecorators === other.experimentalDecorators && this.disableAutomaticTypeAcquisition === other.disableAutomaticTypeAcquisition - && arrays.equals(this.tsServerPluginPaths, other.tsServerPluginPaths); + && arrays.equals(this.tsServerPluginPaths, other.tsServerPluginPaths) + && this.useSeparateSyntaxServer === other.useSeparateSyntaxServer; } private static fixPathPrefixes(inspectValue: string): string { @@ -139,4 +142,8 @@ export class TypeScriptServiceConfiguration { private static extractLocale(configuration: vscode.WorkspaceConfiguration): string | null { return configuration.get('typescript.locale', null); } + + private static readUseSeparateSyntaxServer(configuration: vscode.WorkspaceConfiguration): boolean { + return configuration.get('typescript.tsserver.useSeparateSyntaxServer', true); + } } diff --git a/extensions/typescript-language-features/src/utils/electron.ts b/extensions/typescript-language-features/src/utils/electron.ts index ff69c8c8cc9..ea16bae4277 100644 --- a/extensions/typescript-language-features/src/utils/electron.ts +++ b/extensions/typescript-language-features/src/utils/electron.ts @@ -7,13 +7,27 @@ import * as temp from './temp'; import path = require('path'); import fs = require('fs'); import cp = require('child_process'); +import process = require('process'); const getRootTempDir = (() => { let dir: string | undefined; return () => { if (!dir) { - dir = temp.getTempFile(`vscode-typescript`); + dir = temp.getTempFile(`vscode-typescript${process.platform !== 'win32' && process.getuid ? process.getuid() : ''}`); + } + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir); + } + return dir; + }; +})(); + +export const getInstanceDir = (() => { + let dir: string | undefined; + return () => { + if (!dir) { + dir = path.join(getRootTempDir(), temp.makeRandomHexString(20)); } if (!fs.existsSync(dir)) { fs.mkdirSync(dir); @@ -23,7 +37,7 @@ const getRootTempDir = (() => { })(); export function getTempFile(prefix: string): string { - return path.join(getRootTempDir(), `${prefix}-${temp.makeRandomHexString(20)}.tmp`); + return path.join(getInstanceDir(), `${prefix}-${temp.makeRandomHexString(20)}.tmp`); } function generatePatchedEnv(env: any, modulePath: string): any { diff --git a/extensions/typescript-language-features/src/utils/languageDescription.ts b/extensions/typescript-language-features/src/utils/languageDescription.ts index 32cec300ebd..79f9ce9f47b 100644 --- a/extensions/typescript-language-features/src/utils/languageDescription.ts +++ b/extensions/typescript-language-features/src/utils/languageDescription.ts @@ -9,7 +9,7 @@ export const enum DiagnosticLanguage { TypeScript } -export const allDiagnosticLangauges = [DiagnosticLanguage.JavaScript, DiagnosticLanguage.TypeScript]; +export const allDiagnosticLanguages = [DiagnosticLanguage.JavaScript, DiagnosticLanguage.TypeScript]; export interface LanguageDescription { readonly id: string; @@ -17,7 +17,7 @@ export interface LanguageDescription { readonly diagnosticSource: string; readonly diagnosticLanguage: DiagnosticLanguage; readonly modeIds: string[]; - readonly configFile?: string; + readonly configFilePattern?: RegExp; readonly isExternal?: boolean; } @@ -28,13 +28,13 @@ export const standardLanguageDescriptions: LanguageDescription[] = [ diagnosticSource: 'ts', diagnosticLanguage: DiagnosticLanguage.TypeScript, modeIds: [languageModeIds.typescript, languageModeIds.typescriptreact], - configFile: 'tsconfig.json' + configFilePattern: /^tsconfig(\..*)?\.json$/gi }, { id: 'javascript', diagnosticOwner: 'typescript', diagnosticSource: 'ts', diagnosticLanguage: DiagnosticLanguage.JavaScript, modeIds: [languageModeIds.javascript, languageModeIds.javascriptreact], - configFile: 'jsconfig.json' + configFilePattern: /^jsconfig(\..*)?\.json$/gi } ]; diff --git a/extensions/typescript-language-features/src/utils/managedFileContext.ts b/extensions/typescript-language-features/src/utils/managedFileContext.ts index 36cca539ec3..81acf9ad505 100644 --- a/extensions/typescript-language-features/src/utils/managedFileContext.ts +++ b/extensions/typescript-language-features/src/utils/managedFileContext.ts @@ -5,29 +5,25 @@ import * as vscode from 'vscode'; import { isSupportedLanguageMode } from './languageModeIds'; +import { Disposable } from './dispose'; /** * When clause context set when the current file is managed by vscode's built-in typescript extension. */ -export default class ManagedFileContextManager { +export default class ManagedFileContextManager extends Disposable { private static readonly contextName = 'typescript.isManagedFile'; private isInManagedFileContext: boolean = false; - private readonly onDidChangeActiveTextEditorSub: vscode.Disposable; - public constructor( private readonly normalizePath: (resource: vscode.Uri) => string | undefined ) { - this.onDidChangeActiveTextEditorSub = vscode.window.onDidChangeActiveTextEditor(this.onDidChangeActiveTextEditor, this); + super(); + vscode.window.onDidChangeActiveTextEditor(this.onDidChangeActiveTextEditor, this, this._disposables); this.onDidChangeActiveTextEditor(vscode.window.activeTextEditor); } - public dispose() { - this.onDidChangeActiveTextEditorSub.dispose(); - } - private onDidChangeActiveTextEditor(editor?: vscode.TextEditor): any { if (editor) { const isManagedFile = isSupportedLanguageMode(editor.document) && this.normalizePath(editor.document.uri) !== null; diff --git a/extensions/typescript-language-features/src/utils/pluginPathsProvider.ts b/extensions/typescript-language-features/src/utils/pluginPathsProvider.ts index 547660f0649..de6d03cd980 100644 --- a/extensions/typescript-language-features/src/utils/pluginPathsProvider.ts +++ b/extensions/typescript-language-features/src/utils/pluginPathsProvider.ts @@ -9,7 +9,6 @@ import { RelativeWorkspacePathResolver } from './relativePathResolver'; export class TypeScriptPluginPathsProvider { - public readonly relativePathResolver: RelativeWorkspacePathResolver = new RelativeWorkspacePathResolver(); public constructor( private configuration: TypeScriptServiceConfiguration @@ -32,7 +31,7 @@ export class TypeScriptPluginPathsProvider { return [pluginPath]; } - const workspacePath = this.relativePathResolver.asAbsoluteWorkspacePath(pluginPath); + const workspacePath = RelativeWorkspacePathResolver.asAbsoluteWorkspacePath(pluginPath); if (workspacePath !== undefined) { return [workspacePath]; } diff --git a/extensions/typescript-language-features/src/utils/plugins.ts b/extensions/typescript-language-features/src/utils/plugins.ts index 3b0cf217b92..71ce2430cb8 100644 --- a/extensions/typescript-language-features/src/utils/plugins.ts +++ b/extensions/typescript-language-features/src/utils/plugins.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; +import * as arrays from './arrays'; import { Disposable } from './dispose'; -import { memoize } from './memoize'; export interface TypeScriptServerPlugin { readonly path: string; @@ -14,28 +14,45 @@ export interface TypeScriptServerPlugin { readonly languages: ReadonlyArray; } +namespace TypeScriptServerPlugin { + export function equals(a: TypeScriptServerPlugin, b: TypeScriptServerPlugin): boolean { + return a.path === b.path + && a.name === b.name + && a.enableForWorkspaceTypeScriptVersions === b.enableForWorkspaceTypeScriptVersions + && arrays.equals(a.languages, b.languages); + } +} + export class PluginManager extends Disposable { private readonly _pluginConfigurations = new Map(); - @memoize - public get plugins(): ReadonlyArray { - const plugins: TypeScriptServerPlugin[] = []; - for (const extension of vscode.extensions.all) { - const pack = extension.packageJSON; - if (pack.contributes && Array.isArray(pack.contributes.typescriptServerPlugins)) { - for (const plugin of pack.contributes.typescriptServerPlugins) { - plugins.push({ - name: plugin.name, - enableForWorkspaceTypeScriptVersions: !!plugin.enableForWorkspaceTypeScriptVersions, - path: extension.extensionPath, - languages: Array.isArray(plugin.languages) ? plugin.languages : [], - }); - } + private _plugins: Map> | undefined; + + constructor() { + super(); + + vscode.extensions.onDidChange(() => { + if (!this._plugins) { + return; } - } - return plugins; + const newPlugins = this.readPlugins(); + if (!arrays.equals(arrays.flatten(Array.from(this._plugins.values())), arrays.flatten(Array.from(newPlugins.values())), TypeScriptServerPlugin.equals)) { + this._plugins = newPlugins; + this._onDidUpdatePlugins.fire(this); + } + }, undefined, this._disposables); } + public get plugins(): ReadonlyArray { + if (!this._plugins) { + this._plugins = this.readPlugins(); + } + return arrays.flatten(Array.from(this._plugins.values())); + } + + private readonly _onDidUpdatePlugins = this._register(new vscode.EventEmitter()); + public readonly onDidChangePlugins = this._onDidUpdatePlugins.event; + private readonly _onDidUpdateConfig = this._register(new vscode.EventEmitter<{ pluginId: string, config: {} }>()); public readonly onDidUpdateConfig = this._onDidUpdateConfig.event; @@ -47,4 +64,26 @@ export class PluginManager extends Disposable { public configurations(): IterableIterator<[string, {}]> { return this._pluginConfigurations.entries(); } + + private readPlugins() { + const pluginMap = new Map>(); + for (const extension of vscode.extensions.all) { + const pack = extension.packageJSON; + if (pack.contributes && Array.isArray(pack.contributes.typescriptServerPlugins)) { + const plugins: TypeScriptServerPlugin[] = []; + for (const plugin of pack.contributes.typescriptServerPlugins) { + plugins.push({ + name: plugin.name, + enableForWorkspaceTypeScriptVersions: !!plugin.enableForWorkspaceTypeScriptVersions, + path: extension.extensionPath, + languages: Array.isArray(plugin.languages) ? plugin.languages : [], + }); + } + if (plugins.length) { + pluginMap.set(extension.id, plugins); + } + } + } + return pluginMap; + } } \ No newline at end of file diff --git a/extensions/typescript-language-features/src/utils/previewer.ts b/extensions/typescript-language-features/src/utils/previewer.ts index aa698b2c163..f4a17274960 100644 --- a/extensions/typescript-language-features/src/utils/previewer.ts +++ b/extensions/typescript-language-features/src/utils/previewer.ts @@ -14,7 +14,7 @@ function getTagBodyText(tag: Proto.JSDocTagInfo): string | undefined { switch (tag.name) { case 'example': case 'default': - // Convert to markdown code block if it not already one + // Convert to markdown code block if it is not already one if (tag.text.match(/^\s*[~`]{3}/g)) { return tag.text; } diff --git a/extensions/typescript-language-features/src/utils/projectStatus.ts b/extensions/typescript-language-features/src/utils/projectStatus.ts index 4eb9b8c7686..15aa72a80d0 100644 --- a/extensions/typescript-language-features/src/utils/projectStatus.ts +++ b/extensions/typescript-language-features/src/utils/projectStatus.ts @@ -23,7 +23,12 @@ class ExcludeHintItem { constructor( private readonly telemetryReporter: TelemetryReporter ) { - this._item = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 98 /* to the right of typescript version status (99) */); + this._item = vscode.window.createStatusBarItem({ + id: 'status.typescript.exclude', + name: localize('statusExclude', "TypeScript: Configure Excludes"), + alignment: vscode.StatusBarAlignment.Right, + priority: 98 /* to the right of typescript version status (99) */ + }); this._item.command = 'js.projectStatus.command'; } diff --git a/extensions/typescript-language-features/src/utils/relativePathResolver.ts b/extensions/typescript-language-features/src/utils/relativePathResolver.ts index 85b72a55d6b..64dff66fb53 100644 --- a/extensions/typescript-language-features/src/utils/relativePathResolver.ts +++ b/extensions/typescript-language-features/src/utils/relativePathResolver.ts @@ -6,7 +6,7 @@ import * as path from 'path'; import * as vscode from 'vscode'; export class RelativeWorkspacePathResolver { - public asAbsoluteWorkspacePath(relativePath: string): string | undefined { + public static asAbsoluteWorkspacePath(relativePath: string): string | undefined { for (const root of vscode.workspace.workspaceFolders || []) { const rootPrefixes = [`./${root.name}/`, `${root.name}/`, `.\\${root.name}\\`, `${root.name}\\`]; for (const rootPrefix of rootPrefixes) { diff --git a/extensions/typescript-language-features/src/utils/snippetForFunctionCall.ts b/extensions/typescript-language-features/src/utils/snippetForFunctionCall.ts index 7eab1e21ba9..fbf2868d101 100644 --- a/extensions/typescript-language-features/src/utils/snippetForFunctionCall.ts +++ b/extensions/typescript-language-features/src/utils/snippetForFunctionCall.ts @@ -68,7 +68,7 @@ function getParameterListParts( break; case PConst.DisplayPartKind.parameterName: - if (parenCount === 1 && isInMethod) { + if (parenCount === 1 && braceCount === 0 && isInMethod) { // Only take top level paren names const next = displayParts[i + 1]; // Skip optional parameters diff --git a/extensions/typescript-language-features/src/utils/surveyor.ts b/extensions/typescript-language-features/src/utils/surveyor.ts index bf3ba4ad601..2af183be12e 100644 --- a/extensions/typescript-language-features/src/utils/surveyor.ts +++ b/extensions/typescript-language-features/src/utils/surveyor.ts @@ -103,7 +103,7 @@ class Survey { } private get triggerCount(): number { - const count = this.memento.get(this.triggerCountMementoKey); + const count = this.memento.get(this.triggerCountMementoKey); return !count || isNaN(+count) ? 0 : +count; } diff --git a/extensions/typescript-language-features/src/utils/telemetry.ts b/extensions/typescript-language-features/src/utils/telemetry.ts index e3b5f09adc7..fe6ea8d292a 100644 --- a/extensions/typescript-language-features/src/utils/telemetry.ts +++ b/extensions/typescript-language-features/src/utils/telemetry.ts @@ -13,15 +13,14 @@ interface PackageInfo { readonly aiKey: string; } -export default class TelemetryReporter { - private _reporter: VsCodeTelemetryReporter | null = null; +export default interface TelemetryReporter { + logTelemetry(eventName: string, properties?: { [prop: string]: string }): void; - dispose() { - if (this._reporter) { - this._reporter.dispose(); - this._reporter = null; - } - } + dispose(): void; +} + +export class VSCodeTelemetryReporter implements TelemetryReporter { + private _reporter: VsCodeTelemetryReporter | null = null; constructor( private readonly clientVersionDelegate: () => string @@ -45,6 +44,13 @@ export default class TelemetryReporter { } } + public dispose() { + if (this._reporter) { + this._reporter.dispose(); + this._reporter = null; + } + } + @memoize private get reporter(): VsCodeTelemetryReporter | null { if (this.packageInfo && this.packageInfo.aiKey) { diff --git a/extensions/typescript-language-features/src/utils/temp.ts b/extensions/typescript-language-features/src/utils/temp.ts index 79c5cf751d0..2af5f1732b0 100644 --- a/extensions/typescript-language-features/src/utils/temp.ts +++ b/extensions/typescript-language-features/src/utils/temp.ts @@ -7,7 +7,7 @@ import path = require('path'); import os = require('os'); export function makeRandomHexString(length: number): string { - let chars = ['0', '1', '2', '3', '4', '5', '6', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; + const chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; let result = ''; for (let i = 0; i < length; i++) { const idx = Math.floor(chars.length * Math.random()); diff --git a/extensions/typescript-language-features/src/utils/tracer.ts b/extensions/typescript-language-features/src/utils/tracer.ts index c80254c79a0..f7ca0d674e3 100644 --- a/extensions/typescript-language-features/src/utils/tracer.ts +++ b/extensions/typescript-language-features/src/utils/tracer.ts @@ -50,7 +50,7 @@ export default class Tracer { return result; } - public traceRequest(request: Proto.Request, responseExpected: boolean, queueLength: number): void { + public traceRequest(serverId: string, request: Proto.Request, responseExpected: boolean, queueLength: number): void { if (this.trace === Trace.Off) { return; } @@ -58,10 +58,10 @@ export default class Tracer { if (this.trace === Trace.Verbose && request.arguments) { data = `Arguments: ${JSON.stringify(request.arguments, null, 4)}`; } - this.logTrace(`Sending request: ${request.command} (${request.seq}). Response expected: ${responseExpected ? 'yes' : 'no'}. Current queue length: ${queueLength}`, data); + this.logTrace(serverId, `Sending request: ${request.command} (${request.seq}). Response expected: ${responseExpected ? 'yes' : 'no'}. Current queue length: ${queueLength}`, data); } - public traceResponse(response: Proto.Response, startTime: number): void { + public traceResponse(serverId: string, response: Proto.Response, startTime: number): void { if (this.trace === Trace.Off) { return; } @@ -69,17 +69,17 @@ export default class Tracer { if (this.trace === Trace.Verbose && response.body) { data = `Result: ${JSON.stringify(response.body, null, 4)}`; } - this.logTrace(`Response received: ${response.command} (${response.request_seq}). Request took ${Date.now() - startTime} ms. Success: ${response.success} ${!response.success ? '. Message: ' + response.message : ''}`, data); + this.logTrace(serverId, `Response received: ${response.command} (${response.request_seq}). Request took ${Date.now() - startTime} ms. Success: ${response.success} ${!response.success ? '. Message: ' + response.message : ''}`, data); } - public traceRequestCompleted(command: string, request_seq: number, startTime: number): any { + public traceRequestCompleted(serverId: string, command: string, request_seq: number, startTime: number): any { if (this.trace === Trace.Off) { return; } - this.logTrace(`Async response received: ${command} (${request_seq}). Request took ${Date.now() - startTime} ms.`); + this.logTrace(serverId, `Async response received: ${command} (${request_seq}). Request took ${Date.now() - startTime} ms.`); } - public traceEvent(event: Proto.Event): void { + public traceEvent(serverId: string, event: Proto.Event): void { if (this.trace === Trace.Off) { return; } @@ -87,12 +87,12 @@ export default class Tracer { if (this.trace === Trace.Verbose && event.body) { data = `Data: ${JSON.stringify(event.body, null, 4)}`; } - this.logTrace(`Event received: ${event.event} (${event.seq}).`, data); + this.logTrace(serverId, `Event received: ${event.event} (${event.seq}).`, data); } - public logTrace(message: string, data?: any): void { + public logTrace(serverId: string, message: string, data?: any): void { if (this.trace !== Trace.Off) { - this.logger.logLevel('Trace', message, data); + this.logger.logLevel('Trace', `<${serverId}> ${message}`, data); } } } \ No newline at end of file diff --git a/extensions/typescript-language-features/src/utils/tsconfigProvider.ts b/extensions/typescript-language-features/src/utils/tsconfigProvider.ts index 7e2b85ef2d0..fe939032029 100644 --- a/extensions/typescript-language-features/src/utils/tsconfigProvider.ts +++ b/extensions/typescript-language-features/src/utils/tsconfigProvider.ts @@ -6,6 +6,7 @@ import * as vscode from 'vscode'; export interface TSConfig { readonly path: string; + readonly posixPath: string; readonly workspaceFolder?: vscode.WorkspaceFolder; } @@ -20,6 +21,7 @@ export default class TsConfigProvider { if (root) { configs.set(config.fsPath, { path: config.fsPath, + posixPath: config.path, workspaceFolder: root }); } diff --git a/extensions/typescript-language-features/src/utils/typeConverters.ts b/extensions/typescript-language-features/src/utils/typeConverters.ts index 36a20544fee..37947b38810 100644 --- a/extensions/typescript-language-features/src/utils/typeConverters.ts +++ b/extensions/typescript-language-features/src/utils/typeConverters.ts @@ -13,9 +13,12 @@ import { ITypeScriptServiceClient } from '../typescriptService'; export namespace Range { export const fromTextSpan = (span: Proto.TextSpan): vscode.Range => + fromLocations(span.start, span.end); + + export const fromLocations = (start: Proto.Location, end: Proto.Location): vscode.Range => new vscode.Range( - Math.max(0, span.start.line - 1), Math.max(span.start.offset - 1, 0), - Math.max(0, span.end.line - 1), Math.max(0, span.end.offset - 1)); + Math.max(0, start.line - 1), Math.max(start.offset - 1, 0), + Math.max(0, end.line - 1), Math.max(0, end.offset - 1)); export const toFileRangeRequestArgs = (file: string, range: vscode.Range): Proto.FileRangeRequestArgs => ({ file, @@ -38,6 +41,11 @@ export namespace Position { export const fromLocation = (tslocation: Proto.Location): vscode.Position => new vscode.Position(tslocation.line - 1, tslocation.offset - 1); + export const toLocation = (vsPosition: vscode.Position): Proto.Location => ({ + line: vsPosition.line + 1, + offset: vsPosition.character + 1, + }); + export const toFileLocationRequestArgs = (file: string, position: vscode.Position): Proto.FileLocationRequestArgs => ({ file, line: position.line + 1, @@ -63,16 +71,17 @@ export namespace WorkspaceEdit { edits: Iterable ): vscode.WorkspaceEdit { return withFileCodeEdits(new vscode.WorkspaceEdit(), client, edits); - } + export function withFileCodeEdits( workspaceEdit: vscode.WorkspaceEdit, client: ITypeScriptServiceClient, edits: Iterable ): vscode.WorkspaceEdit { for (const edit of edits) { + const resource = client.toResource(edit.fileName); for (const textChange of edit.textChanges) { - workspaceEdit.replace(client.toResource(edit.fileName), + workspaceEdit.replace(resource, Range.fromTextSpan(textChange), textChange.newText); } diff --git a/extensions/typescript-language-features/src/utils/typingsStatus.ts b/extensions/typescript-language-features/src/utils/typingsStatus.ts index 78f303f0f39..066fda960df 100644 --- a/extensions/typescript-language-features/src/utils/typingsStatus.ts +++ b/extensions/typescript-language-features/src/utils/typingsStatus.ts @@ -6,18 +6,19 @@ import * as vscode from 'vscode'; import { loadMessageBundle } from 'vscode-nls'; import { ITypeScriptServiceClient } from '../typescriptService'; +import { Disposable } from './dispose'; const localize = loadMessageBundle(); const typingsInstallTimeout = 30 * 1000; -export default class TypingsStatus extends vscode.Disposable { +export default class TypingsStatus extends Disposable { private _acquiringTypings: { [eventId: string]: NodeJS.Timer } = Object.create({}); private _client: ITypeScriptServiceClient; private _subscriptions: vscode.Disposable[] = []; constructor(client: ITypeScriptServiceClient) { - super(() => this.dispose()); + super(); this._client = client; this._subscriptions.push( @@ -28,6 +29,7 @@ export default class TypingsStatus extends vscode.Disposable { } public dispose(): void { + super.dispose(); this._subscriptions.forEach(x => x.dispose()); for (const eventId of Object.keys(this._acquiringTypings)) { diff --git a/extensions/typescript-language-features/src/utils/versionPicker.ts b/extensions/typescript-language-features/src/utils/versionPicker.ts index afbda6ef206..d1827002ee3 100644 --- a/extensions/typescript-language-features/src/utils/versionPicker.ts +++ b/extensions/typescript-language-features/src/utils/versionPicker.ts @@ -113,7 +113,7 @@ export class TypeScriptVersionPicker { return { oldVersion: previousVersion, newVersion: shippedVersion }; case MessageAction.learnMore: - vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://go.microsoft.com/fwlink/?linkid=839919')); + vscode.env.openExternal(vscode.Uri.parse('https://go.microsoft.com/fwlink/?linkid=839919')); return { oldVersion: this.currentVersion }; default: diff --git a/extensions/typescript-language-features/src/utils/versionProvider.ts b/extensions/typescript-language-features/src/utils/versionProvider.ts index eb50009cfd6..8e9e9a2a8c6 100644 --- a/extensions/typescript-language-features/src/utils/versionProvider.ts +++ b/extensions/typescript-language-features/src/utils/versionProvider.ts @@ -9,8 +9,8 @@ import * as nls from 'vscode-nls'; import API from './api'; import { TypeScriptServiceConfiguration } from './configuration'; import { RelativeWorkspacePathResolver } from './relativePathResolver'; -const localize = nls.loadMessageBundle(); +const localize = nls.loadMessageBundle(); export class TypeScriptVersion { constructor( @@ -27,10 +27,10 @@ export class TypeScriptVersion { } public get isValid(): boolean { - return this.version !== undefined; + return this.apiVersion !== undefined; } - public get version(): API | undefined { + public get apiVersion(): API | undefined { const version = this.getTypeScriptVersion(this.tsServerPath); if (version) { return version; @@ -46,7 +46,7 @@ export class TypeScriptVersion { } public get versionString(): string { - const version = this.version; + const version = this.apiVersion; return version ? version.versionString : localize( 'couldNotLoadTsVersion', 'Could not load the TypeScript version at this path'); } @@ -88,7 +88,6 @@ export class TypeScriptVersion { } export class TypeScriptVersionProvider { - private readonly relativePathResolver: RelativeWorkspacePathResolver = new RelativeWorkspacePathResolver(); public constructor( private configuration: TypeScriptServiceConfiguration @@ -109,7 +108,7 @@ export class TypeScriptVersionProvider { return globals[0]; } } - return undefined; + return this.contributedTsNextVersion; } public get localVersion(): TypeScriptVersion | undefined { @@ -138,22 +137,37 @@ export class TypeScriptVersionProvider { } public get bundledVersion(): TypeScriptVersion { - try { - const { extensionPath } = vscode.extensions.getExtension('vscode.typescript-language-features')!; - const typescriptPath = path.join(extensionPath, '../node_modules/typescript/lib'); - const bundledVersion = new TypeScriptVersion(typescriptPath, ''); - if (bundledVersion.isValid) { - return bundledVersion; - } - } catch (e) { - // noop + const version = this.getContributedVersion('vscode.typescript-language-features', ['..', 'node_modules']); + if (version) { + return version; } + vscode.window.showErrorMessage(localize( 'noBundledServerFound', 'VS Code\'s tsserver was deleted by another application such as a misbehaving virus detection tool. Please reinstall VS Code.')); throw new Error('Could not find bundled tsserver.js'); } + private get contributedTsNextVersion(): TypeScriptVersion | undefined { + return this.getContributedVersion('ms-vscode.vscode-typescript-next', ['node_modules']); + } + + private getContributedVersion(extensionId: string, pathToTs: readonly string[]): TypeScriptVersion | undefined { + try { + const extension = vscode.extensions.getExtension(extensionId); + if (extension) { + const typescriptPath = path.join(extension.extensionPath, ...pathToTs, 'typescript', 'lib'); + const bundledVersion = new TypeScriptVersion(typescriptPath, ''); + if (bundledVersion.isValid) { + return bundledVersion; + } + } + } catch { + // noop + } + return undefined; + } + private get localTsdkVersions(): TypeScriptVersion[] { const localTsdk = this.configuration.localTsdk; return localTsdk ? this.loadVersionsFromSetting(localTsdk) : []; @@ -164,7 +178,7 @@ export class TypeScriptVersionProvider { return [new TypeScriptVersion(tsdkPathSetting)]; } - const workspacePath = this.relativePathResolver.asAbsoluteWorkspacePath(tsdkPathSetting); + const workspacePath = RelativeWorkspacePathResolver.asAbsoluteWorkspacePath(tsdkPathSetting); if (workspacePath !== undefined) { return [new TypeScriptVersion(workspacePath, tsdkPathSetting)]; } diff --git a/extensions/typescript-language-features/src/utils/versionStatus.ts b/extensions/typescript-language-features/src/utils/versionStatus.ts index 6d7940c9a8a..07bd2e5921a 100644 --- a/extensions/typescript-language-features/src/utils/versionStatus.ts +++ b/extensions/typescript-language-features/src/utils/versionStatus.ts @@ -6,21 +6,25 @@ import * as vscode from 'vscode'; import * as languageModeIds from './languageModeIds'; import { TypeScriptVersion } from './versionProvider'; +import { Disposable } from './dispose'; +import * as nls from 'vscode-nls'; -export default class VersionStatus { - private readonly _onChangeEditorSub: vscode.Disposable; +const localize = nls.loadMessageBundle(); + +export default class VersionStatus extends Disposable { private readonly _versionBarEntry: vscode.StatusBarItem; constructor( private readonly _normalizePath: (resource: vscode.Uri) => string | undefined ) { - this._versionBarEntry = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 99 /* to the right of editor status (100) */); - this._onChangeEditorSub = vscode.window.onDidChangeActiveTextEditor(this.showHideStatus, this); - } - - public dispose() { - this._versionBarEntry.dispose(); - this._onChangeEditorSub.dispose(); + super(); + this._versionBarEntry = this._register(vscode.window.createStatusBarItem({ + id: 'status.typescript.version', + name: localize('typescriptVersion', "TypeScript: Version"), + alignment: vscode.StatusBarAlignment.Right, + priority: 99 /* to the right of editor status (100) */ + })); + vscode.window.onDidChangeActiveTextEditor(this.showHideStatus, this, this._disposables); } public onDidChangeTypeScriptVersion(version: TypeScriptVersion) { diff --git a/extensions/typescript-language-features/yarn.lock b/extensions/typescript-language-features/yarn.lock index ff4f999787c..683f002c727 100644 --- a/extensions/typescript-language-features/yarn.lock +++ b/extensions/typescript-language-features/yarn.lock @@ -2,10 +2,42 @@ # yarn lockfile v1 -"@types/node@8.0.33": - version "8.0.33" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd" - integrity sha512-vmCdO8Bm1ExT+FWfC9sd9r4jwqM7o97gGy2WBshkkXbf/2nLAJQUrZfIhw27yVOtLUev6kSZc4cav/46KbDd8A== +"@types/events@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== + +"@types/glob@*": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + +"@types/node@*": + version "12.0.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.2.tgz#3452a24edf9fea138b48fad4a0a028a683da1e40" + integrity sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA== + +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== + +"@types/rimraf@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.2.tgz#7f0fc3cf0ff0ad2a99bb723ae1764f30acaf8b6e" + integrity sha512-Hm/bnWq0TCy7jmjeN5bKYij9vw5GrDFWME4IuxV08278NtU/VdGbzsBohcCUJ7+QMqmUq5hpRKB39HeQWJjztQ== + dependencies: + "@types/glob" "*" + "@types/node" "*" "@types/semver@^5.5.0": version "5.5.0" @@ -58,10 +90,10 @@ ansi-wrap@0.1.0: resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= -applicationinsights@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.6.tgz#bc201810de91cea910dab34e8ad35ecde488edeb" - integrity sha512-VQT3kBpJVPw5fCO5n+WUeSx0VHjxFtD7znYbILBlVgOS9/cMDuGFmV2Br3ObzFyZUDGNbEfW36fD1y2/vAiCKw== +applicationinsights@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" + integrity sha512-KzOOGdphOS/lXWMFZe5440LUdFbrLpMvh2SaRxn7BmiI550KAoSb2gIhiq6kJZ9Ir3AxRRztjhzif+e5P5IXIg== dependencies: diagnostic-channel "0.2.0" diagnostic-channel-publishers "0.2.1" @@ -630,6 +662,18 @@ glob@^5.0.3: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.3: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glogg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" @@ -1490,6 +1534,13 @@ rimraf@2: dependencies: glob "^7.0.5" +rimraf@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -1810,12 +1861,12 @@ vinyl@^2.0.1, vinyl@^2.0.2: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" -vscode-extension-telemetry@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.0.tgz#3cdcb61d03829966bd04b5f11471a1e40d6abaad" - integrity sha512-WVCnP+uLxlqB6UD98yQNV47mR5Rf79LFxpuZhSPhEf0Sb4tPZed3a63n003/dchhOwyCTCBuNN4n8XKJkLEI1Q== +vscode-extension-telemetry@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b" + integrity sha512-TkKKG/B/J94DP5qf6xWB4YaqlhWDg6zbbqVx7Bz//stLQNnfE9XS1xm3f6fl24c5+bnEK0/wHgMgZYKIKxPeUA== dependencies: - applicationinsights "1.0.6" + applicationinsights "1.0.8" vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/vb/cgmanifest.json b/extensions/vb/cgmanifest.json index 4cb7d33e04b..23523f36abb 100644 --- a/extensions/vb/cgmanifest.json +++ b/extensions/vb/cgmanifest.json @@ -29,4 +29,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/vb/package.json b/extensions/vb/package.json index 3aed441f932..f41732e9d6e 100644 --- a/extensions/vb/package.json +++ b/extensions/vb/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "scripts": { "update-grammar": "node ../../build/npm/update-grammar.js textmate/asp.vb.net.tmbundle Syntaxes/ASP%20VB.net.plist ./syntaxes/asp-vb-net.tmlanguage.json" diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 4ee121e1b1b..beaa216d77d 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -3,6 +3,7 @@ "description": "API tests for VS Code", "version": "0.0.1", "publisher": "vscode", + "license": "MIT", "enableProposedApi": true, "private": true, "main": "horse", @@ -49,7 +50,7 @@ }, "devDependencies": { "@types/mocha": "2.2.43", - "@types/node": "^8.10.25", + "@types/node": "^10.14.8", "mocha-junit-reporter": "^1.17.0", "mocha-multi-reporters": "^1.1.7", "typescript": "^1.6.2", diff --git a/extensions/vscode-api-tests/src/memfs.ts b/extensions/vscode-api-tests/src/memfs.ts new file mode 100644 index 00000000000..2b4a5f751ab --- /dev/null +++ b/extensions/vscode-api-tests/src/memfs.ts @@ -0,0 +1,229 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +import * as path from 'path'; +import * as vscode from 'vscode'; + +class File implements vscode.FileStat { + + type: vscode.FileType; + ctime: number; + mtime: number; + size: number; + + name: string; + data?: Uint8Array; + + constructor(name: string) { + this.type = vscode.FileType.File; + this.ctime = Date.now(); + this.mtime = Date.now(); + this.size = 0; + this.name = name; + } +} + +class Directory implements vscode.FileStat { + + type: vscode.FileType; + ctime: number; + mtime: number; + size: number; + + name: string; + entries: Map; + + constructor(name: string) { + this.type = vscode.FileType.Directory; + this.ctime = Date.now(); + this.mtime = Date.now(); + this.size = 0; + this.name = name; + this.entries = new Map(); + } +} + +export type Entry = File | Directory; + +export class MemFS implements vscode.FileSystemProvider { + + readonly scheme = 'fake-fs'; + + readonly root = new Directory(''); + + // --- manage file metadata + + stat(uri: vscode.Uri): vscode.FileStat { + return this._lookup(uri, false); + } + + readDirectory(uri: vscode.Uri): [string, vscode.FileType][] { + const entry = this._lookupAsDirectory(uri, false); + let result: [string, vscode.FileType][] = []; + for (const [name, child] of entry.entries) { + result.push([name, child.type]); + } + return result; + } + + // --- manage file contents + + readFile(uri: vscode.Uri): Uint8Array { + const data = this._lookupAsFile(uri, false).data; + if (data) { + return data; + } + throw vscode.FileSystemError.FileNotFound(); + } + + writeFile(uri: vscode.Uri, content: Uint8Array, options: { create: boolean, overwrite: boolean }): void { + let basename = path.posix.basename(uri.path); + let parent = this._lookupParentDirectory(uri); + let entry = parent.entries.get(basename); + if (entry instanceof Directory) { + throw vscode.FileSystemError.FileIsADirectory(uri); + } + if (!entry && !options.create) { + throw vscode.FileSystemError.FileNotFound(uri); + } + if (entry && options.create && !options.overwrite) { + throw vscode.FileSystemError.FileExists(uri); + } + if (!entry) { + entry = new File(basename); + parent.entries.set(basename, entry); + this._fireSoon({ type: vscode.FileChangeType.Created, uri }); + } + entry.mtime = Date.now(); + entry.size = content.byteLength; + entry.data = content; + + this._fireSoon({ type: vscode.FileChangeType.Changed, uri }); + } + + // --- manage files/folders + + rename(oldUri: vscode.Uri, newUri: vscode.Uri, options: { overwrite: boolean }): void { + + if (!options.overwrite && this._lookup(newUri, true)) { + throw vscode.FileSystemError.FileExists(newUri); + } + + let entry = this._lookup(oldUri, false); + let oldParent = this._lookupParentDirectory(oldUri); + + let newParent = this._lookupParentDirectory(newUri); + let newName = path.posix.basename(newUri.path); + + oldParent.entries.delete(entry.name); + entry.name = newName; + newParent.entries.set(newName, entry); + + this._fireSoon( + { type: vscode.FileChangeType.Deleted, uri: oldUri }, + { type: vscode.FileChangeType.Created, uri: newUri } + ); + } + + delete(uri: vscode.Uri): void { + let dirname = uri.with({ path: path.posix.dirname(uri.path) }); + let basename = path.posix.basename(uri.path); + let parent = this._lookupAsDirectory(dirname, false); + if (!parent.entries.has(basename)) { + throw vscode.FileSystemError.FileNotFound(uri); + } + parent.entries.delete(basename); + parent.mtime = Date.now(); + parent.size -= 1; + this._fireSoon({ type: vscode.FileChangeType.Changed, uri: dirname }, { uri, type: vscode.FileChangeType.Deleted }); + } + + createDirectory(uri: vscode.Uri): void { + let basename = path.posix.basename(uri.path); + let dirname = uri.with({ path: path.posix.dirname(uri.path) }); + let parent = this._lookupAsDirectory(dirname, false); + + let entry = new Directory(basename); + parent.entries.set(entry.name, entry); + parent.mtime = Date.now(); + parent.size += 1; + this._fireSoon({ type: vscode.FileChangeType.Changed, uri: dirname }, { type: vscode.FileChangeType.Created, uri }); + } + + // --- lookup + + private _lookup(uri: vscode.Uri, silent: false): Entry; + private _lookup(uri: vscode.Uri, silent: boolean): Entry | undefined; + private _lookup(uri: vscode.Uri, silent: boolean): Entry | undefined { + let parts = uri.path.split('/'); + let entry: Entry = this.root; + for (const part of parts) { + if (!part) { + continue; + } + let child: Entry | undefined; + if (entry instanceof Directory) { + child = entry.entries.get(part); + } + if (!child) { + if (!silent) { + throw vscode.FileSystemError.FileNotFound(uri); + } else { + return undefined; + } + } + entry = child; + } + return entry; + } + + private _lookupAsDirectory(uri: vscode.Uri, silent: boolean): Directory { + let entry = this._lookup(uri, silent); + if (entry instanceof Directory) { + return entry; + } + throw vscode.FileSystemError.FileNotADirectory(uri); + } + + private _lookupAsFile(uri: vscode.Uri, silent: boolean): File { + let entry = this._lookup(uri, silent); + if (entry instanceof File) { + return entry; + } + throw vscode.FileSystemError.FileIsADirectory(uri); + } + + private _lookupParentDirectory(uri: vscode.Uri): Directory { + const dirname = uri.with({ path: path.posix.dirname(uri.path) }); + return this._lookupAsDirectory(dirname, false); + } + + // --- manage file events + + private _emitter = new vscode.EventEmitter(); + private _bufferedEvents: vscode.FileChangeEvent[] = []; + private _fireSoonHandle?: NodeJS.Timer; + + readonly onDidChangeFile: vscode.Event = this._emitter.event; + + watch(_resource: vscode.Uri): vscode.Disposable { + // ignore, fires for all changes... + return new vscode.Disposable(() => { }); + } + + private _fireSoon(...events: vscode.FileChangeEvent[]): void { + this._bufferedEvents.push(...events); + + if (this._fireSoonHandle) { + clearTimeout(this._fireSoonHandle); + } + + this._fireSoonHandle = setTimeout(() => { + this._emitter.fire(this._bufferedEvents); + this._bufferedEvents.length = 0; + }, 5); + } +} diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts index c007e2168f0..9ea76e6a119 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts @@ -74,23 +74,6 @@ suite('commands namespace tests', () => { }); - test('api-command: vscode.previewHtml', async function () { - - let registration = workspace.registerTextDocumentContentProvider('speciale', { - provideTextDocumentContent(uri) { - return `content of URI ${uri.toString()}`; - } - }); - - let virtualDocumentUri = Uri.parse('speciale://authority/path'); - let title = 'A title'; - - const success = await commands.executeCommand('vscode.previewHtml', virtualDocumentUri, ViewColumn.Three, title); - assert.ok(success); - registration.dispose(); - - }); - test('api-command: vscode.diff', function () { let registration = workspace.registerTextDocumentContentProvider('sc', { @@ -122,7 +105,7 @@ suite('commands namespace tests', () => { }); test('api-command: vscode.open', function () { - let uri = Uri.file(join(workspace.rootPath || '', './image.png')); + let uri = Uri.parse(workspace.workspaceFolders![0].uri.toString() + '/image.png'); let a = commands.executeCommand('vscode.open', uri).then(() => assert.ok(true), () => assert.ok(false)); let b = commands.executeCommand('vscode.open', uri, ViewColumn.Two).then(() => assert.ok(true), () => assert.ok(false)); let c = commands.executeCommand('vscode.open').then(() => assert.ok(false), () => assert.ok(true)); @@ -130,4 +113,31 @@ suite('commands namespace tests', () => { return Promise.all([a, b, c, d]); }); -}); \ No newline at end of file + + test('onDidExecuteCommand', async function () { + let args: any[]; + let d1 = commands.registerCommand('t1', function () { + args = [...arguments]; + }); + + + const p = new Promise((resolve, reject) => { + + let d2 = commands.onDidExecuteCommand(event => { + d2.dispose(); + d1.dispose(); + + try { + assert.equal(event.command, 't1'); + assert.deepEqual(args, event.arguments); + resolve(); + } catch (e) { + reject(e); + } + }); + }); + + await commands.executeCommand('t1', { foo: 1 }); + await p; + }); +}); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts index 80ad28ddf57..9b6c6d82897 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts @@ -195,4 +195,27 @@ suite('editor tests', () => { ); }); }); + + test('throw when using invalid edit', async function () { + + await withRandomFileEditor('foo', editor => { + + return new Promise((resolve, reject) => { + + editor.edit(edit => { + edit.insert(new Position(0, 0), 'bar'); + setTimeout(() => { + try { + edit.insert(new Position(0, 0), 'bar'); + reject(new Error('expected error')); + } catch (err) { + assert.ok(true); + resolve(); + } + }, 0); + }); + }); + }); + + }); }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts index 31d6d4ce312..112c76139b7 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { env } from 'vscode'; +import { env, extensions, ExtensionKind } from 'vscode'; suite('env-namespace', () => { @@ -14,6 +14,7 @@ suite('env-namespace', () => { assert.equal(typeof env.appName, 'string'); assert.equal(typeof env.machineId, 'string'); assert.equal(typeof env.sessionId, 'string'); + assert.equal(typeof env.shell, 'string'); }); test('env is readonly', function () { @@ -22,6 +23,25 @@ suite('env-namespace', () => { assert.throws(() => (env as any).appName = '234'); assert.throws(() => (env as any).machineId = '234'); assert.throws(() => (env as any).sessionId = '234'); + assert.throws(() => (env as any).shell = '234'); + }); + + test('env.remoteName', function () { + const remoteName = env.remoteName; + const apiTestExtension = extensions.getExtension('vscode.vscode-api-tests'); + const testResolverExtension = extensions.getExtension('vscode.vscode-test-resolver'); + if (typeof remoteName === 'undefined') { + assert.ok(apiTestExtension); + assert.ok(testResolverExtension); + assert.equal(ExtensionKind.UI, apiTestExtension!.extensionKind); + assert.equal(ExtensionKind.UI, testResolverExtension!.extensionKind); + } else if (typeof remoteName === 'string') { + assert.ok(apiTestExtension); + assert.ok(!testResolverExtension); // we currently can only access extensions that run on same host + assert.equal(ExtensionKind.Workspace, apiTestExtension!.extensionKind); + } else { + assert.fail(); + } }); }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts index 9983c542be3..0a828ad8d73 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts @@ -6,10 +6,24 @@ import * as assert from 'assert'; import { join } from 'path'; import * as vscode from 'vscode'; -import { createRandomFile } from '../utils'; +import { createRandomFile, testFs } from '../utils'; suite('languages namespace tests', () => { + const isWindows = process.platform === 'win32'; + + function positionToString(p: vscode.Position) { + return `[${p.character}/${p.line}]`; + } + + function rangeToString(r: vscode.Range) { + return `[${positionToString(r.start)}/${positionToString(r.end)}]`; + } + + function assertEqualRange(actual: vscode.Range, expected: vscode.Range, message?: string) { + assert.equal(rangeToString(actual), rangeToString(expected), message); + } + test('setTextDocumentLanguage -> close/open event', async function () { const file = await createRandomFile('foo\nbar\nbar'); const doc = await vscode.workspace.openTextDocument(file); @@ -77,6 +91,31 @@ suite('languages namespace tests', () => { assert.ok(found); }); + test('link detector', async function () { + const uri = await createRandomFile('class A { // http://a.com }', undefined, '.java'); + const doc = await vscode.workspace.openTextDocument(uri); + + const target = vscode.Uri.file(isWindows ? 'c:\\foo\\bar' : '/foo/bar'); + const range = new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 5)); + + const linkProvider: vscode.DocumentLinkProvider = { + provideDocumentLinks: _doc => { + return [new vscode.DocumentLink(range, target)]; + } + }; + vscode.languages.registerDocumentLinkProvider({ language: 'java', scheme: testFs.scheme }, linkProvider); + + const links = await vscode.commands.executeCommand('vscode.executeLinkProvider', doc.uri); + assert.equal(2, links && links.length); + let [link1, link2] = links!.sort((l1, l2) => l1.range.start.compareTo(l2.range.start)); + + assert.equal(target.toString(), link1.target && link1.target.toString()); + assertEqualRange(range, link1.range); + + assert.equal('http://a.com/', link2.target && link2.target.toString()); + assertEqualRange(new vscode.Range(new vscode.Position(0, 13), new vscode.Position(0, 25)), link2.range); + }); + test('diagnostics & CodeActionProvider', async function () { class D2 extends vscode.Diagnostic { @@ -141,7 +180,8 @@ suite('languages namespace tests', () => { await vscode.workspace.openTextDocument(uri); const result = await vscode.commands.executeCommand('vscode.executeCompletionItemProvider', uri, new vscode.Position(1, 0)); r1.dispose(); - assert.ok(ran); - assert.equal(result!.items[0].label, 'foo'); + assert.ok(ran, 'Provider has not been invoked'); + assert.ok(result!.items.some(i => i.label === 'foo'), 'Results do not include "foo"'); }); + }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts new file mode 100644 index 00000000000..b008ecb1b0e --- /dev/null +++ b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts @@ -0,0 +1,354 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { window, Pseudoterminal, EventEmitter, TerminalDimensions, workspace, ConfigurationTarget } from 'vscode'; +import { doesNotThrow, equal, ok, deepEqual } from 'assert'; + +suite('window namespace tests', () => { + suiteSetup(async () => { + // Disable conpty in integration tests because of https://github.com/microsoft/vscode/issues/76548 + await workspace.getConfiguration('terminal.integrated').update('windowsEnableConpty', false, ConfigurationTarget.Global); + }); + suite('Terminal', () => { + test('sendText immediately after createTerminal should not throw', (done) => { + const reg1 = window.onDidOpenTerminal(term => { + equal(terminal, term); + terminal.dispose(); + reg1.dispose(); + const reg2 = window.onDidCloseTerminal(() => { + reg2.dispose(); + done(); + }); + }); + const terminal = window.createTerminal(); + doesNotThrow(terminal.sendText.bind(terminal, 'echo "foo"')); + }); + + test('onDidCloseTerminal event fires when terminal is disposed', (done) => { + const reg1 = window.onDidOpenTerminal(term => { + equal(terminal, term); + terminal.dispose(); + reg1.dispose(); + const reg2 = window.onDidCloseTerminal(() => { + reg2.dispose(); + done(); + }); + }); + const terminal = window.createTerminal(); + }); + + test('processId immediately after createTerminal should fetch the pid', (done) => { + const reg1 = window.onDidOpenTerminal(term => { + equal(terminal, term); + reg1.dispose(); + terminal.processId.then(id => { + ok(id > 0); + terminal.dispose(); + const reg2 = window.onDidCloseTerminal(() => { + reg2.dispose(); + done(); + }); + }); + }); + const terminal = window.createTerminal(); + }); + + test('name in constructor should set terminal.name', (done) => { + const reg1 = window.onDidOpenTerminal(term => { + equal(terminal, term); + terminal.dispose(); + reg1.dispose(); + const reg2 = window.onDidCloseTerminal(() => { + reg2.dispose(); + done(); + }); + }); + const terminal = window.createTerminal('a'); + equal(terminal.name, 'a'); + }); + + test('onDidOpenTerminal should fire when a terminal is created', (done) => { + const reg1 = window.onDidOpenTerminal(term => { + equal(term.name, 'b'); + reg1.dispose(); + const reg2 = window.onDidCloseTerminal(() => { + reg2.dispose(); + done(); + }); + terminal.dispose(); + }); + const terminal = window.createTerminal('b'); + }); + // test('onDidChangeActiveTerminal should fire when new terminals are created', (done) => { + // const reg1 = window.onDidChangeActiveTerminal((active: Terminal | undefined) => { + // equal(active, terminal); + // equal(active, window.activeTerminal); + // reg1.dispose(); + // const reg2 = window.onDidChangeActiveTerminal((active: Terminal | undefined) => { + // equal(active, undefined); + // equal(active, window.activeTerminal); + // reg2.dispose(); + // done(); + // }); + // terminal.dispose(); + // }); + // const terminal = window.createTerminal(); + // terminal.show(); + // }); + + // test('onDidChangeTerminalDimensions should fire when new terminals are created', (done) => { + // const reg1 = window.onDidChangeTerminalDimensions(async (event: TerminalDimensionsChangeEvent) => { + // equal(event.terminal, terminal1); + // equal(typeof event.dimensions.columns, 'number'); + // equal(typeof event.dimensions.rows, 'number'); + // ok(event.dimensions.columns > 0); + // ok(event.dimensions.rows > 0); + // reg1.dispose(); + // let terminal2: Terminal; + // const reg2 = window.onDidOpenTerminal((newTerminal) => { + // // This is guarantees to fire before dimensions change event + // if (newTerminal !== terminal1) { + // terminal2 = newTerminal; + // reg2.dispose(); + // } + // }); + // let firstCalled = false; + // let secondCalled = false; + // const reg3 = window.onDidChangeTerminalDimensions((event: TerminalDimensionsChangeEvent) => { + // if (event.terminal === terminal1) { + // // The original terminal should fire dimension change after a split + // firstCalled = true; + // } else if (event.terminal !== terminal1) { + // // The new split terminal should fire dimension change + // secondCalled = true; + // } + // if (firstCalled && secondCalled) { + // let firstDisposed = false; + // let secondDisposed = false; + // const reg4 = window.onDidCloseTerminal(term => { + // if (term === terminal1) { + // firstDisposed = true; + // } + // if (term === terminal2) { + // secondDisposed = true; + // } + // if (firstDisposed && secondDisposed) { + // reg4.dispose(); + // done(); + // } + // }); + // terminal1.dispose(); + // terminal2.dispose(); + // reg3.dispose(); + // } + // }); + // await timeout(500); + // commands.executeCommand('workbench.action.terminal.split'); + // }); + // const terminal1 = window.createTerminal({ name: 'test' }); + // terminal1.show(); + // }); + + suite('hideFromUser', () => { + // test('should fire onDidWriteData correctly', done => { + // const terminal = window.createTerminal({ name: 'bg', hideFromUser: true }); + // let data = ''; + // terminal.onDidWriteData(e => { + // data += e; + // if (data.indexOf('foo') !== -1) { + // const reg3 = window.onDidCloseTerminal(() => { + // reg3.dispose(); + // done(); + // }); + // terminal.dispose(); + // } + // }); + // terminal.sendText('foo'); + // }); + + test('should be available to terminals API', done => { + const terminal = window.createTerminal({ name: 'bg', hideFromUser: true }); + window.onDidOpenTerminal(t => { + equal(t, terminal); + equal(t.name, 'bg'); + ok(window.terminals.indexOf(terminal) !== -1); + const reg3 = window.onDidCloseTerminal(() => { + reg3.dispose(); + done(); + }); + terminal.dispose(); + }); + }); + }); + + suite('window.onDidWriteTerminalData', () => { + test('should listen to all future terminal data events', (done) => { + const openEvents: string[] = []; + const dataEvents: { name: string, data: string }[] = []; + const closeEvents: string[] = []; + const reg1 = window.onDidOpenTerminal(e => openEvents.push(e.name)); + const reg2 = window.onDidWriteTerminalData(e => dataEvents.push({ name: e.terminal.name, data: e.data })); + const reg3 = window.onDidCloseTerminal(e => { + closeEvents.push(e.name); + if (closeEvents.length === 2) { + deepEqual(openEvents, [ 'test1', 'test2' ]); + deepEqual(dataEvents, [ { name: 'test1', data: 'write1' }, { name: 'test2', data: 'write2' } ]); + deepEqual(closeEvents, [ 'test1', 'test2' ]); + reg1.dispose(); + reg2.dispose(); + reg3.dispose(); + done(); + } + }); + + const term1Write = new EventEmitter(); + const term1Close = new EventEmitter(); + window.createTerminal({ name: 'test1', pty: { + onDidWrite: term1Write.event, + onDidClose: term1Close.event, + open: () => { + term1Write.fire('write1'); + term1Close.fire(); + const term2Write = new EventEmitter(); + const term2Close = new EventEmitter(); + window.createTerminal({ name: 'test2', pty: { + onDidWrite: term2Write.event, + onDidClose: term2Close.event, + open: () => { + term2Write.fire('write2'); + term2Close.fire(); + }, + close: () => {} + }}); + }, + close: () => {} + }}); + }); + }); + + suite('Extension pty terminals', () => { + test('should fire onDidOpenTerminal and onDidCloseTerminal', (done) => { + const reg1 = window.onDidOpenTerminal(term => { + equal(term.name, 'c'); + reg1.dispose(); + const reg2 = window.onDidCloseTerminal(() => { + reg2.dispose(); + done(); + }); + term.dispose(); + }); + const pty: Pseudoterminal = { + onDidWrite: new EventEmitter().event, + open: () => {}, + close: () => {} + }; + window.createTerminal({ name: 'c', pty }); + }); + + test('should fire Terminal.onData on write', (done) => { + const reg1 = window.onDidOpenTerminal(async term => { + equal(terminal, term); + reg1.dispose(); + const reg2 = terminal.onDidWriteData(data => { + equal(data, 'bar'); + reg2.dispose(); + const reg3 = window.onDidCloseTerminal(() => { + reg3.dispose(); + done(); + }); + terminal.dispose(); + }); + await startPromise; + writeEmitter.fire('bar'); + }); + let startResolve: () => void; + const startPromise: Promise = new Promise(r => startResolve = r); + const writeEmitter = new EventEmitter(); + const pty: Pseudoterminal = { + onDidWrite: writeEmitter.event, + open: () => startResolve(), + close: () => {} + }; + const terminal = window.createTerminal({ name: 'foo', pty }); + }); + + test('should not provide dimensions on start as the terminal has not been shown yet', (done) => { + const reg1 = window.onDidOpenTerminal(term => { + equal(terminal, term); + reg1.dispose(); + }); + const pty: Pseudoterminal = { + onDidWrite: new EventEmitter().event, + open: (dimensions) => { + equal(dimensions, undefined); + const reg3 = window.onDidCloseTerminal(() => { + reg3.dispose(); + done(); + }); + // Show a terminal and wait a brief period before dispose, this will cause + // the panel to init it's dimenisons and be provided to following terminals. + // The following test depends on this. + terminal.show(); + setTimeout(() => terminal.dispose(), 200); + }, + close: () => {} + }; + const terminal = window.createTerminal({ name: 'foo', pty }); + }); + + test('should provide dimensions on start as the terminal has been shown', (done) => { + const reg1 = window.onDidOpenTerminal(term => { + equal(terminal, term); + reg1.dispose(); + }); + const pty: Pseudoterminal = { + onDidWrite: new EventEmitter().event, + open: (dimensions) => { + // This test depends on Terminal.show being called some time before such + // that the panel dimensions are initialized and cached. + ok(dimensions!.columns > 0); + ok(dimensions!.rows > 0); + const reg3 = window.onDidCloseTerminal(() => { + reg3.dispose(); + done(); + }); + terminal.dispose(); + }, + close: () => {} + }; + const terminal = window.createTerminal({ name: 'foo', pty }); + }); + + test('should respect dimension overrides', (done) => { + const reg1 = window.onDidOpenTerminal(term => { + equal(terminal, term); + reg1.dispose(); + term.show(); + const reg2 = window.onDidChangeTerminalDimensions(e => { + equal(e.dimensions.columns, 10); + equal(e.dimensions.rows, 5); + equal(e.terminal, terminal); + reg2.dispose(); + const reg3 = window.onDidCloseTerminal(() => { + reg3.dispose(); + done(); + }); + terminal.dispose(); + }); + overrideDimensionsEmitter.fire({ columns: 10, rows: 5 }); + }); + const writeEmitter = new EventEmitter(); + const overrideDimensionsEmitter = new EventEmitter(); + const pty: Pseudoterminal = { + onDidWrite: writeEmitter.event, + onDidOverrideDimensions: overrideDimensionsEmitter.event, + open: () => {}, + close: () => {} + }; + const terminal = window.createTerminal({ name: 'foo', pty }); + }); + }); + }); +}); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/types.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/types.test.ts new file mode 100644 index 00000000000..b2ad43d30b0 --- /dev/null +++ b/extensions/vscode-api-tests/src/singlefolder-tests/types.test.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import 'mocha'; +import * as assert from 'assert'; +import * as vscode from 'vscode'; + + +suite('types', () => { + + test('static properties, es5 compat class', function () { + + + assert.ok(vscode.ThemeIcon.File instanceof vscode.ThemeIcon); + assert.ok(vscode.ThemeIcon.Folder instanceof vscode.ThemeIcon); + assert.ok(vscode.CodeActionKind.Empty instanceof vscode.CodeActionKind); + assert.ok(vscode.CodeActionKind.QuickFix instanceof vscode.CodeActionKind); + assert.ok(vscode.CodeActionKind.Refactor instanceof vscode.CodeActionKind); + assert.ok(vscode.CodeActionKind.RefactorExtract instanceof vscode.CodeActionKind); + assert.ok(vscode.CodeActionKind.RefactorInline instanceof vscode.CodeActionKind); + assert.ok(vscode.CodeActionKind.RefactorRewrite instanceof vscode.CodeActionKind); + assert.ok(vscode.CodeActionKind.Source instanceof vscode.CodeActionKind); + assert.ok(vscode.CodeActionKind.SourceOrganizeImports instanceof vscode.CodeActionKind); + assert.ok(vscode.CodeActionKind.SourceFixAll instanceof vscode.CodeActionKind); + // assert.ok(vscode.QuickInputButtons.Back instanceof vscode.QuickInputButtons); never was an instance + + }); +}); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts index d211db9565b..4be0218ab64 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts @@ -7,7 +7,7 @@ import 'mocha'; import * as assert from 'assert'; import * as vscode from 'vscode'; import { join } from 'path'; -import { closeAllEditors, disposeAll } from '../utils'; +import { closeAllEditors, disposeAll, conditionalTest } from '../utils'; const webviewId = 'myWebview'; @@ -82,7 +82,7 @@ suite('Webview tests', () => { } }); - test('webviews should preserve vscode API state when they are hidden', async () => { + conditionalTest('webviews should preserve vscode API state when they are hidden', async () => { const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true })); const ready = getMesssage(webview); webview.webview.html = createHtmlDocumentWithBody(/*html*/` @@ -125,31 +125,14 @@ suite('Webview tests', () => { assert.strictEqual(secondResponse.value, 1); }); - test('webviews should preserve their context when they are moved between view columns', async () => { + conditionalTest('webviews should preserve their context when they are moved between view columns', async () => { const doc = await vscode.workspace.openTextDocument(testDocument); await vscode.window.showTextDocument(doc, vscode.ViewColumn.One); // Open webview in same column const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true })); const ready = getMesssage(webview); - webview.webview.html = createHtmlDocumentWithBody(/*html*/` - `); + webview.webview.html = statefulWebviewHtml; await ready; const firstResponse = await sendRecieveMessage(webview, { type: 'add' }); @@ -163,29 +146,11 @@ suite('Webview tests', () => { assert.strictEqual(secondResponse.value, 1); }); - test('webviews with retainContextWhenHidden should preserve their context when they are hidden', async () => { + conditionalTest('webviews with retainContextWhenHidden should preserve their context when they are hidden', async () => { const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true })); const ready = getMesssage(webview); - webview.webview.html = createHtmlDocumentWithBody(/*html*/` - `); + webview.webview.html = statefulWebviewHtml; await ready; const firstResponse = await sendRecieveMessage(webview, { type: 'add' }); @@ -203,7 +168,7 @@ suite('Webview tests', () => { assert.strictEqual(secondResponse.value, 1); }); - test('webviews with retainContextWhenHidden should preserve their page position when hidden', async () => { + conditionalTest('webviews with retainContextWhenHidden should preserve their page position when hidden', async () => { const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true })); const ready = getMesssage(webview); webview.webview.html = createHtmlDocumentWithBody(/*html*/` @@ -244,7 +209,34 @@ suite('Webview tests', () => { assert.strictEqual(secondResponse.value, 100); }); - test('webviews should only be able to load resources from workspace by default', async () => { + conditionalTest('webviews with retainContextWhenHidden should be able to recive messages while hidden', async () => { + const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true })); + const ready = getMesssage(webview); + + webview.webview.html = statefulWebviewHtml; + await ready; + + const firstResponse = await sendRecieveMessage(webview, { type: 'add' }); + assert.strictEqual((await firstResponse).value, 1); + + // Swap away from the webview + const doc = await vscode.workspace.openTextDocument(testDocument); + await vscode.window.showTextDocument(doc); + + // Try posting a message to our hidden webview + const secondResponse = await sendRecieveMessage(webview, { type: 'add' }); + assert.strictEqual((await secondResponse).value, 2); + + // Now show webview again + webview.reveal(vscode.ViewColumn.One); + + // We should still have old state + const thirdResponse = await sendRecieveMessage(webview, { type: 'get' }); + assert.strictEqual(thirdResponse.value, 2); + }); + + + conditionalTest('webviews should only be able to load resources from workspace by default', async () => { const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true })); webview.webview.html = createHtmlDocumentWithBody(/*html*/` @@ -259,15 +251,18 @@ suite('Webview tests', () => { }); `); - const workspaceRootUri = vscode.Uri.file(vscode.workspace.rootPath!).with({ scheme: 'vscode-resource' }); + async function toWebviewResource(path: string) { + const root = await webview.webview.toWebviewResource(vscode.Uri.file(vscode.workspace.rootPath!)); + return root.toString() + path; + } { - const imagePath = workspaceRootUri.toString() + '/image.png'; + const imagePath = await toWebviewResource('/image.png'); const response = sendRecieveMessage(webview, { src: imagePath }); assert.strictEqual((await response).value, true); } { - const imagePath = workspaceRootUri.toString() + '/no-such-image.png'; + const imagePath = await toWebviewResource('/no-such-image.png'); const response = sendRecieveMessage(webview, { src: imagePath }); assert.strictEqual((await response).value, false); } @@ -278,7 +273,7 @@ suite('Webview tests', () => { } }); - test('webviews should allow overriding allowed resource paths using localResourceRoots', async () => { + conditionalTest('webviews should allow overriding allowed resource paths using localResourceRoots', async () => { const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, localResourceRoots: [vscode.Uri.file(join(vscode.workspace.rootPath!, 'sub'))] @@ -307,6 +302,38 @@ suite('Webview tests', () => { assert.strictEqual((await response).value, false); } }); + + test('webviews should have real view column after they are created, #56097', async () => { + const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.Active }, { enableScripts: true })); + + // Since we used a symbolic column, we don't know what view column the webview will actually show in at first + assert.strictEqual(webview.viewColumn, undefined); + + let changed = false; + const viewStateChanged = new Promise((resolve) => { + webview.onDidChangeViewState(e => { + if (changed) { + throw new Error('Only expected a single view state change'); + } + changed = true; + resolve(e); + }, undefined, disposables); + }); + + assert.strictEqual((await viewStateChanged).webviewPanel.viewColumn, vscode.ViewColumn.One); + + const firstResponse = getMesssage(webview); + webview.webview.html = createHtmlDocumentWithBody(/*html*/` + `); + + webview.webview.postMessage({ value: 1 }); + await firstResponse; + assert.strictEqual(webview.viewColumn, vscode.ViewColumn.One); + + }); }); function createHtmlDocumentWithBody(body: string): string { @@ -324,6 +351,27 @@ function createHtmlDocumentWithBody(body: string): string { `; } +const statefulWebviewHtml = createHtmlDocumentWithBody(/*html*/ ` + `); + + function getMesssage(webview: vscode.WebviewPanel): Promise { return new Promise(resolve => { const sub = webview.webview.onDidReceiveMessage(message => { diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts index 707508b723c..c2ec4f13681 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { workspace, window, commands, ViewColumn, TextEditorViewColumnChangeEvent, Uri, Selection, Position, CancellationTokenSource, TextEditorSelectionChangeKind, Terminal } from 'vscode'; +import { workspace, window, commands, ViewColumn, TextEditorViewColumnChangeEvent, Uri, Selection, Position, CancellationTokenSource, TextEditorSelectionChangeKind } from 'vscode'; import { join } from 'path'; import { closeAllEditors, pathEquals, createRandomFile } from '../utils'; @@ -380,13 +380,13 @@ suite('window namespace tests', () => { assert.equal(await two, 'notempty'); }); - - test('showQuickPick, accept first', async function () { - const pick = window.showQuickPick(['eins', 'zwei', 'drei']); - await new Promise(resolve => setTimeout(resolve, 10)); // Allow UI to update. - await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); - assert.equal(await pick, 'eins'); - }); + // TODO@chrmarti Disabled due to flaky behaviour (https://github.com/Microsoft/vscode/issues/70887) + // test('showQuickPick, accept first', async function () { + // const pick = window.showQuickPick(['eins', 'zwei', 'drei']); + // await new Promise(resolve => setTimeout(resolve, 10)); // Allow UI to update. + // await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); + // assert.equal(await pick, 'eins'); + // }); test('showQuickPick, accept second', async function () { const resolves: ((value: string) => void)[] = []; @@ -435,18 +435,19 @@ suite('window namespace tests', () => { return unexpected; }); - test('showQuickPick, keep selection (Microsoft/vscode-azure-account#67)', async function () { - const picks = window.showQuickPick([ - { label: 'eins' }, - { label: 'zwei', picked: true }, - { label: 'drei', picked: true } - ], { - canPickMany: true - }); - await new Promise(resolve => setTimeout(resolve, 10)); // Allow UI to update. - await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); - assert.deepStrictEqual((await picks)!.map(pick => pick.label), ['zwei', 'drei']); - }); + // TODO@chrmarti Disabled due to flaky behaviour (https://github.com/Microsoft/vscode/issues/70887) + // test('showQuickPick, keep selection (Microsoft/vscode-azure-account#67)', async function () { + // const picks = window.showQuickPick([ + // { label: 'eins' }, + // { label: 'zwei', picked: true }, + // { label: 'drei', picked: true } + // ], { + // canPickMany: true + // }); + // await new Promise(resolve => setTimeout(resolve, 10)); // Allow UI to update. + // await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); + // assert.deepStrictEqual((await picks)!.map(pick => pick.label), ['zwei', 'drei']); + // }); test('showQuickPick, undefined on cancel', function () { const source = new CancellationTokenSource(); @@ -517,19 +518,20 @@ suite('window namespace tests', () => { return Promise.all([a, b]); }); - test('showWorkspaceFolderPick', async function () { - const p = window.showWorkspaceFolderPick(undefined); + // TODO@chrmarti Disabled due to flaky behaviour (https://github.com/Microsoft/vscode/issues/70887) + // test('showWorkspaceFolderPick', async function () { + // const p = window.showWorkspaceFolderPick(undefined); - await timeout(10); - await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); - try { - await p; - assert.ok(true); - } - catch (_error) { - assert.ok(false); - } - }); + // await timeout(10); + // await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); + // try { + // await p; + // assert.ok(true); + // } + // catch (_error) { + // assert.ok(false); + // } + // }); test('Default value for showInput Box not accepted when it fails validateInput, reversing #33691', async function () { const result = window.showInputBox({ @@ -566,138 +568,4 @@ suite('window namespace tests', () => { }); }); - - suite('Terminal', () => { - test('sendText immediately after createTerminal should not throw', () => { - const terminal = window.createTerminal(); - assert.doesNotThrow(terminal.sendText.bind(terminal, 'echo "foo"')); - terminal.dispose(); - }); - - test('onDidCloseTerminal event fires when terminal is disposed', (done) => { - const terminal = window.createTerminal(); - const reg = window.onDidCloseTerminal((eventTerminal) => { - assert.equal(terminal, eventTerminal); - reg.dispose(); - done(); - }); - terminal.dispose(); - }); - - test('processId immediately after createTerminal should fetch the pid', (done) => { - const terminal = window.createTerminal(); - terminal.processId.then(id => { - assert.ok(id > 0); - terminal.dispose(); - done(); - }); - }); - - test('name in constructor should set terminal.name', () => { - const terminal = window.createTerminal('a'); - assert.equal(terminal.name, 'a'); - terminal.dispose(); - }); - - test('onDidOpenTerminal should fire when a terminal is created', (done) => { - const reg1 = window.onDidOpenTerminal(term => { - assert.equal(term.name, 'b'); - reg1.dispose(); - const reg2 = window.onDidCloseTerminal(() => { - reg2.dispose(); - done(); - }); - terminal.dispose(); - }); - const terminal = window.createTerminal('b'); - }); - - test('createTerminalRenderer should fire onDidOpenTerminal and onDidCloseTerminal', (done) => { - const reg1 = window.onDidOpenTerminal(term => { - assert.equal(term.name, 'c'); - reg1.dispose(); - const reg2 = window.onDidCloseTerminal(() => { - reg2.dispose(); - done(); - }); - term.dispose(); - }); - window.createTerminalRenderer('c'); - }); - - test('terminal renderers should get maximum dimensions set when shown', (done) => { - let terminal: Terminal; - const reg1 = window.onDidOpenTerminal(term => { - reg1.dispose(); - term.show(); - terminal = term; - }); - const renderer = window.createTerminalRenderer('foo'); - const reg2 = renderer.onDidChangeMaximumDimensions(dimensions => { - assert.ok(dimensions.columns > 0); - assert.ok(dimensions.rows > 0); - reg2.dispose(); - const reg3 = window.onDidCloseTerminal(() => { - reg3.dispose(); - done(); - }); - terminal.dispose(); - }); - }); - - test('TerminalRenderer.write should fire Terminal.onData', (done) => { - const reg1 = window.onDidOpenTerminal(terminal => { - reg1.dispose(); - const reg2 = terminal.onDidWriteData(data => { - assert.equal(data, 'bar'); - reg2.dispose(); - const reg3 = window.onDidCloseTerminal(() => { - reg3.dispose(); - done(); - }); - terminal.dispose(); - }); - renderer.write('bar'); - }); - const renderer = window.createTerminalRenderer('foo'); - }); - - test('Terminal.sendText should fire Terminal.onInput', (done) => { - const reg1 = window.onDidOpenTerminal(terminal => { - reg1.dispose(); - const reg2 = renderer.onDidAcceptInput(data => { - assert.equal(data, 'bar'); - reg2.dispose(); - const reg3 = window.onDidCloseTerminal(() => { - reg3.dispose(); - done(); - }); - terminal.dispose(); - }); - terminal.sendText('bar', false); - }); - const renderer = window.createTerminalRenderer('foo'); - }); - - test('onDidChangeActiveTerminal should fire when new terminals are created', (done) => { - const reg1 = window.onDidChangeActiveTerminal((active: Terminal | undefined) => { - assert.equal(active, terminal); - assert.equal(active, window.activeTerminal); - reg1.dispose(); - const reg2 = window.onDidChangeActiveTerminal((active: Terminal | undefined) => { - assert.equal(active, undefined); - assert.equal(active, window.activeTerminal); - reg2.dispose(); - done(); - }); - terminal.dispose(); - }); - const terminal = window.createTerminal(); - terminal.show(); - }); - }); }); - -async function timeout(ms = 0): Promise { - return new Promise(resolve => setTimeout(() => resolve(), ms)); -} \ No newline at end of file diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.fs.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.fs.test.ts new file mode 100644 index 00000000000..06728e206d9 --- /dev/null +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.fs.test.ts @@ -0,0 +1,141 @@ +/*--------------------------------------------------------------------------------------------- + * 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 vscode from 'vscode'; +import { posix } from 'path'; + +suite('workspace-fs', () => { + + let root: vscode.Uri; + + suiteSetup(function () { + root = vscode.workspace.workspaceFolders![0]!.uri; + }); + + test('fs.stat', async function () { + const stat = await vscode.workspace.fs.stat(root); + assert.equal(stat.type, vscode.FileType.Directory); + + assert.equal(typeof stat.size, 'number'); + assert.equal(typeof stat.mtime, 'number'); + assert.equal(typeof stat.ctime, 'number'); + + + const entries = await vscode.workspace.fs.readDirectory(root); + assert.ok(entries.length > 0); + + // find far.js + const tuple = entries.find(tuple => tuple[0] === 'far.js')!; + assert.ok(tuple); + assert.equal(tuple[0], 'far.js'); + assert.equal(tuple[1], vscode.FileType.File); + }); + + test('fs.stat - bad scheme', async function () { + try { + await vscode.workspace.fs.stat(vscode.Uri.parse('foo:/bar/baz/test.txt')); + assert.ok(false); + } catch { + assert.ok(true); + } + }); + + test('fs.stat - missing file', async function () { + try { + await vscode.workspace.fs.stat(root.with({ path: root.path + '.bad' })); + assert.ok(false); + } catch (e) { + assert.ok(true); + } + }); + + test('fs.write/stat/delete', async function () { + + const uri = root.with({ path: posix.join(root.path, 'new.file') }); + await vscode.workspace.fs.writeFile(uri, Buffer.from('HELLO')); + + const stat = await vscode.workspace.fs.stat(uri); + assert.equal(stat.type, vscode.FileType.File); + + await vscode.workspace.fs.delete(uri); + + try { + await vscode.workspace.fs.stat(uri); + assert.ok(false); + } catch { + assert.ok(true); + } + }); + + test('fs.delete folder', async function () { + + const folder = root.with({ path: posix.join(root.path, 'folder') }); + const file = root.with({ path: posix.join(root.path, 'folder/file') }); + + await vscode.workspace.fs.createDirectory(folder); + await vscode.workspace.fs.writeFile(file, Buffer.from('FOO')); + + await vscode.workspace.fs.stat(folder); + await vscode.workspace.fs.stat(file); + + // ensure non empty folder cannot be deleted + try { + await vscode.workspace.fs.delete(folder, { recursive: false, useTrash: false }); + assert.ok(false); + } catch { + await vscode.workspace.fs.stat(folder); + await vscode.workspace.fs.stat(file); + } + + // ensure non empty folder cannot be deleted is DEFAULT + try { + await vscode.workspace.fs.delete(folder); // recursive: false as default + assert.ok(false); + } catch { + await vscode.workspace.fs.stat(folder); + await vscode.workspace.fs.stat(file); + } + + // delete non empty folder with recursive-flag + await vscode.workspace.fs.delete(folder, { recursive: true, useTrash: false }); + + // esnure folder/file are gone + try { + await vscode.workspace.fs.stat(folder); + assert.ok(false); + } catch { + assert.ok(true); + } + try { + await vscode.workspace.fs.stat(file); + assert.ok(false); + } catch { + assert.ok(true); + } + }); + + test('throws FileSystemError', async function () { + + try { + await vscode.workspace.fs.stat(vscode.Uri.file(`/c468bf16-acfd-4591-825e-2bcebba508a3/71b1f274-91cb-4c19-af00-8495eaab4b73/4b60cb48-a6f2-40ea-9085-0936f4a8f59a.tx6`)); + assert.ok(false); + } catch (e) { + assert.ok(e instanceof vscode.FileSystemError); + assert.equal(e.name, vscode.FileSystemError.FileNotFound().name); + } + }); + + test('throws FileSystemError', async function () { + + try { + await vscode.workspace.fs.stat(vscode.Uri.parse('foo:/bar')); + assert.ok(false); + } catch (e) { + assert.ok(e instanceof vscode.FileSystemError); + assert.equal(e.name, vscode.FileSystemError.Unavailable().name); + } + }); +}); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.tasks.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.tasks.test.ts new file mode 100644 index 00000000000..daef120762c --- /dev/null +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.tasks.test.ts @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------------------------- + * 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 vscode from 'vscode'; + +suite('workspace-namespace', () => { + + suite('Tasks', () => { + + test('CustomExecution2 task should start and shutdown successfully', (done) => { + interface CustomTestingTaskDefinition extends vscode.TaskDefinition { + /** + * One of the task properties. This can be used to customize the task in the tasks.json + */ + customProp1: string; + } + const taskType: string = 'customTesting'; + const taskName = 'First custom task'; + const reg1 = vscode.window.onDidOpenTerminal(term => { + reg1.dispose(); + const reg2 = term.onDidWriteData(e => { + reg2.dispose(); + assert.equal(e, 'testing\r\n'); + term.dispose(); + }); + }); + const taskProvider = vscode.tasks.registerTaskProvider(taskType, { + provideTasks: () => { + const result: vscode.Task[] = []; + const kind: CustomTestingTaskDefinition = { + type: taskType, + customProp1: 'testing task one' + }; + const writeEmitter = new vscode.EventEmitter(); + const execution = new vscode.CustomExecution2((): Thenable => { + const pty: vscode.Pseudoterminal = { + onDidWrite: writeEmitter.event, + open: () => { + writeEmitter.fire('testing\r\n'); + }, + close: () => { + taskProvider.dispose(); + done(); + } + }; + return Promise.resolve(pty); + }); + const task = new vscode.Task2(kind, vscode.TaskScope.Workspace, taskName, taskType, execution); + result.push(task); + return result; + }, + resolveTask(_task: vscode.Task): vscode.Task | undefined { + assert.fail('resolveTask should not trigger during the test'); + return undefined; + } + }); + vscode.commands.executeCommand('workbench.action.tasks.runTask', `${taskType}: ${taskName}`); + }); + }); +}); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts index e5cf2bd12a4..3617b55f41c 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts @@ -5,10 +5,9 @@ import * as assert from 'assert'; import * as vscode from 'vscode'; -import { createRandomFile, deleteFile, closeAllEditors, pathEquals, rndName, disposeAll } from '../utils'; +import { createRandomFile, deleteFile, closeAllEditors, pathEquals, rndName, disposeAll, testFs } from '../utils'; import { join, posix, basename } from 'path'; import * as fs from 'fs'; -import * as os from 'os'; suite('workspace-namespace', () => { @@ -36,12 +35,14 @@ suite('workspace-namespace', () => { }); test('rootPath', () => { - if (vscode.workspace.rootPath) { - assert.ok(pathEquals(vscode.workspace.rootPath, join(__dirname, '../../testWorkspace'))); - } + assert.ok(pathEquals(vscode.workspace.rootPath!, join(__dirname, '../../testWorkspace'))); assert.throws(() => (vscode.workspace as any).rootPath = 'farboo'); }); + test('workspaceFile', () => { + assert.ok(!vscode.workspace.workspaceFile); + }); + test('workspaceFolders', () => { if (vscode.workspace.workspaceFolders) { assert.equal(vscode.workspace.workspaceFolders.length, 1); @@ -75,7 +76,7 @@ suite('workspace-namespace', () => { }); test('openTextDocument, untitled is dirty', function () { - return vscode.workspace.openTextDocument(vscode.Uri.parse('untitled:' + join(vscode.workspace.rootPath || '', './newfile.txt'))).then(doc => { + return vscode.workspace.openTextDocument(vscode.Uri.parse('untitled:' + join(vscode.workspace.workspaceFolders![0].uri.toString() || '', './newfile.txt'))).then(doc => { assert.equal(doc.uri.scheme, 'untitled'); assert.ok(doc.isDirty); }); @@ -129,8 +130,7 @@ suite('workspace-namespace', () => { assert.ok(fs.existsSync(path)); d0.dispose(); - - return deleteFile(vscode.Uri.file(join(vscode.workspace.rootPath || '', './newfile.txt'))); + fs.unlinkSync(join(vscode.workspace.rootPath || '', './newfile.txt')); }); }); @@ -285,6 +285,30 @@ suite('workspace-namespace', () => { }); }); + test('events: onDidSaveTextDocument fires even for non dirty file when saved', () => { + return createRandomFile().then(file => { + let disposables: vscode.Disposable[] = []; + + let onDidSaveTextDocument = false; + disposables.push(vscode.workspace.onDidSaveTextDocument(e => { + assert.ok(pathEquals(e.uri.fsPath, file.fsPath)); + onDidSaveTextDocument = true; + })); + + return vscode.workspace.openTextDocument(file).then(doc => { + return vscode.window.showTextDocument(doc).then(() => { + return vscode.commands.executeCommand('workbench.action.files.save').then(() => { + assert.ok(onDidSaveTextDocument); + + disposeAll(disposables); + + return deleteFile(file); + }); + }); + }); + }); + }); + test('openTextDocument, with selection', function () { return createRandomFile('foo\nbar\nbar').then(file => { return vscode.workspace.openTextDocument(file).then(doc => { @@ -488,9 +512,37 @@ suite('workspace-namespace', () => { }); test('findFiles', () => { - return vscode.workspace.findFiles('*.js').then((res) => { + return vscode.workspace.findFiles('**/*.png').then((res) => { + assert.equal(res.length, 2); + assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); + }); + }); + + test('findFiles - null exclude', async () => { + await vscode.workspace.findFiles('**/file.txt').then((res) => { + // search.exclude folder is still searched, files.exclude folder is not assert.equal(res.length, 1); - assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'far.js'); + assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'file.txt'); + }); + + await vscode.workspace.findFiles('**/file.txt', null).then((res) => { + // search.exclude and files.exclude folders are both searched + assert.equal(res.length, 2); + assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'file.txt'); + }); + }); + + test('findFiles - exclude', () => { + return vscode.workspace.findFiles('**/*.png').then((res) => { + assert.equal(res.length, 2); + assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); + }); + }); + + test('findFiles, exclude', () => { + return vscode.workspace.findFiles('**/*.png', '**/sub/**').then((res) => { + assert.equal(res.length, 1); + assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); }); }); @@ -568,7 +620,7 @@ suite('workspace-namespace', () => { test('applyEdit should fail when editing renamed from resource', async () => { const resource = await createRandomFile(); - const newResource = vscode.Uri.parse(resource.fsPath + '.1'); + const newResource = vscode.Uri.file(resource.fsPath + '.1'); const edit = new vscode.WorkspaceEdit(); edit.renameFile(resource, newResource); edit.insert(resource, new vscode.Position(0, 0), ''); @@ -648,10 +700,8 @@ suite('workspace-namespace', () => { test('WorkspaceEdit: edit and rename parent folder duplicates resource #42641', async function () { - let dir = join(os.tmpdir(), 'before-' + rndName()); - if (!fs.existsSync(dir)) { - fs.mkdirSync(dir); - } + let dir = vscode.Uri.parse(`${testFs.scheme}:/before-${rndName()}`); + await testFs.createDirectory(dir); let docUri = await createRandomFile('', dir); let docParent = docUri.with({ path: posix.dirname(docUri.path) }); @@ -756,4 +806,29 @@ suite('workspace-namespace', () => { we.deleteFile(docUri, { ignoreIfNotExists: true }); assert.ok(await vscode.workspace.applyEdit(we)); }); + + test('The api workspace.applyEdit drops the TextEdit if there is a RenameFile later #77735', async function () { + + let [f1, f2, f3] = await Promise.all([createRandomFile(), createRandomFile(), createRandomFile()]); + + let we = new vscode.WorkspaceEdit(); + we.insert(f1, new vscode.Position(0, 0), 'f1'); + we.insert(f2, new vscode.Position(0, 0), 'f2'); + we.insert(f3, new vscode.Position(0, 0), 'f3'); + + let f1_ = nameWithUnderscore(f1); + we.renameFile(f1, f1_); + + assert.ok(await vscode.workspace.applyEdit(we)); + + assert.equal((await vscode.workspace.openTextDocument(f3)).getText(), 'f3'); + assert.equal((await vscode.workspace.openTextDocument(f2)).getText(), 'f2'); + assert.equal((await vscode.workspace.openTextDocument(f1_)).getText(), 'f1'); + try { + await vscode.workspace.fs.stat(f1); + assert.ok(false); + } catch { + assert.ok(true); + } + }); }); diff --git a/extensions/vscode-api-tests/src/utils.ts b/extensions/vscode-api-tests/src/utils.ts index 79db77f0d0c..38ede848840 100644 --- a/extensions/vscode-api-tests/src/utils.ts +++ b/extensions/vscode-api-tests/src/utils.ts @@ -4,25 +4,35 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import * as fs from 'fs'; -import * as os from 'os'; -import { join } from 'path'; +import { MemFS } from './memfs'; +import * as assert from 'assert'; export function rndName() { return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); } -export function createRandomFile(contents = '', dir: string = os.tmpdir()): Thenable { - return new Promise((resolve, reject) => { - const tmpFile = join(dir, rndName()); - fs.writeFile(tmpFile, contents, (error) => { - if (error) { - return reject(error); - } +export const testFs = new MemFS(); +vscode.workspace.registerFileSystemProvider(testFs.scheme, testFs); - resolve(vscode.Uri.file(tmpFile)); - }); - }); +export async function createRandomFile(contents = '', dir: vscode.Uri | undefined = undefined, ext = ''): Promise { + let fakeFile: vscode.Uri; + if (dir) { + assert.equal(dir.scheme, testFs.scheme); + fakeFile = dir.with({ path: dir.path + '/' + rndName() + ext }); + } else { + fakeFile = vscode.Uri.parse(`${testFs.scheme}:/${rndName() + ext}`); + } + await testFs.writeFile(fakeFile, Buffer.from(contents), { create: true, overwrite: true }); + return fakeFile; +} + +export async function deleteFile(file: vscode.Uri): Promise { + try { + await testFs.delete(file); + return true; + } catch { + return false; + } } export function pathEquals(path1: string, path2: string): boolean { @@ -34,28 +44,26 @@ export function pathEquals(path1: string, path2: string): boolean { return path1 === path2; } -export function deleteFile(file: vscode.Uri): Thenable { - return new Promise((resolve, reject) => { - fs.unlink(file.fsPath, (err) => { - if (err) { - reject(err); - } else { - resolve(true); - } - }); - }); -} - export function closeAllEditors(): Thenable { return vscode.commands.executeCommand('workbench.action.closeAllEditors'); } export function disposeAll(disposables: vscode.Disposable[]) { - while (disposables.length) { - let item = disposables.pop(); - if (item) { - item.dispose(); + vscode.Disposable.from(...disposables).dispose(); +} + +export function conditionalTest(name: string, testCallback: (done: MochaDone) => void | Thenable) { + if (isTestTypeActive()) { + const async = !!testCallback.length; + if (async) { + test(name, (done) => testCallback(done)); + } else { + test(name, () => (<() => void | Thenable>testCallback)()); } } -} \ No newline at end of file +} + +function isTestTypeActive(): boolean { + return !!vscode.extensions.getExtension('vscode-resolver-test'); +} diff --git a/extensions/vscode-api-tests/src/workspace-tests/workspace.test.ts b/extensions/vscode-api-tests/src/workspace-tests/workspace.test.ts index f28967468a5..f018f581c42 100644 --- a/extensions/vscode-api-tests/src/workspace-tests/workspace.test.ts +++ b/extensions/vscode-api-tests/src/workspace-tests/workspace.test.ts @@ -13,18 +13,18 @@ suite('workspace-namespace', () => { teardown(closeAllEditors); test('rootPath', () => { - if (vscode.workspace.rootPath) { - assert.ok(pathEquals(vscode.workspace.rootPath, join(__dirname, '../../testWorkspace'))); - } + assert.ok(pathEquals(vscode.workspace.rootPath!, join(__dirname, '../../testWorkspace'))); + }); + + test('workspaceFile', () => { + assert.ok(pathEquals(vscode.workspace.workspaceFile!.fsPath, join(__dirname, '../../testworkspace.code-workspace'))); }); test('workspaceFolders', () => { - if (vscode.workspace.workspaceFolders) { - assert.equal(vscode.workspace.workspaceFolders.length, 2); - assert.ok(pathEquals(vscode.workspace.workspaceFolders[0].uri.fsPath, join(__dirname, '../../testWorkspace'))); - assert.ok(pathEquals(vscode.workspace.workspaceFolders[1].uri.fsPath, join(__dirname, '../../testWorkspace2'))); - assert.ok(pathEquals(vscode.workspace.workspaceFolders[1].name, 'Test Workspace 2')); - } + assert.equal(vscode.workspace.workspaceFolders!.length, 2); + assert.ok(pathEquals(vscode.workspace.workspaceFolders![0].uri.fsPath, join(__dirname, '../../testWorkspace'))); + assert.ok(pathEquals(vscode.workspace.workspaceFolders![1].uri.fsPath, join(__dirname, '../../testWorkspace2'))); + assert.ok(pathEquals(vscode.workspace.workspaceFolders![1].name, 'Test Workspace 2')); }); test('getWorkspaceFolder', () => { diff --git a/extensions/vscode-api-tests/testWorkspace/.vscode/settings.json b/extensions/vscode-api-tests/testWorkspace/.vscode/settings.json new file mode 100644 index 00000000000..e9f6fb82156 --- /dev/null +++ b/extensions/vscode-api-tests/testWorkspace/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "search.exclude": { + "**/search-exclude/**": true + }, + "files.exclude": { + "**/files-exclude/**": true + } +} \ No newline at end of file diff --git a/extensions/vscode-api-tests/testWorkspace/files-exclude/file.txt b/extensions/vscode-api-tests/testWorkspace/files-exclude/file.txt new file mode 100644 index 00000000000..1a010b1c0f0 --- /dev/null +++ b/extensions/vscode-api-tests/testWorkspace/files-exclude/file.txt @@ -0,0 +1 @@ +file \ No newline at end of file diff --git a/extensions/vscode-api-tests/testWorkspace/search-exclude/file.txt b/extensions/vscode-api-tests/testWorkspace/search-exclude/file.txt new file mode 100644 index 00000000000..1a010b1c0f0 --- /dev/null +++ b/extensions/vscode-api-tests/testWorkspace/search-exclude/file.txt @@ -0,0 +1 @@ +file \ No newline at end of file diff --git a/extensions/vscode-api-tests/yarn.lock b/extensions/vscode-api-tests/yarn.lock index 74a177b2aea..7585841254a 100644 --- a/extensions/vscode-api-tests/yarn.lock +++ b/extensions/vscode-api-tests/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.43.tgz#03c54589c43ad048cbcbfd63999b55d0424eec27" integrity sha512-xNlAmH+lRJdUMXClMTI9Y0pRqIojdxfm7DHsIxoB2iTzu3fnPmSMEN8SsSx0cdwV36d02PWCWaDUoZPDSln+xw== -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== ajv@^5.1.0: version "5.3.0" diff --git a/extensions/vscode-colorize-tests/package.json b/extensions/vscode-colorize-tests/package.json index 9b43cfa2a6c..702e36e66cd 100644 --- a/extensions/vscode-colorize-tests/package.json +++ b/extensions/vscode-colorize-tests/package.json @@ -3,16 +3,16 @@ "description": "Colorize tests for VS Code", "version": "0.0.1", "publisher": "vscode", + "license": "MIT", "private": true, "engines": { "vscode": "*" }, "scripts": { - "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-colorize-tests ./tsconfig.json", - "postinstall": "node ./node_modules/vscode/bin/install" + "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-colorize-tests ./tsconfig.json" }, "devDependencies": { - "@types/node": "^8.10.25", + "@types/node": "^10.14.8", "mocha-junit-reporter": "^1.17.0", "mocha-multi-reporters": "^1.1.7", "vscode": "1.1.5" diff --git a/extensions/vscode-colorize-tests/src/typings/ref.d.ts b/extensions/vscode-colorize-tests/src/typings/ref.d.ts index 8ea9f802a47..a45a0c6353f 100644 --- a/extensions/vscode-colorize-tests/src/typings/ref.d.ts +++ b/extensions/vscode-colorize-tests/src/typings/ref.d.ts @@ -4,3 +4,4 @@ *--------------------------------------------------------------------------------------------*/ /// +/// diff --git a/extensions/vscode-colorize-tests/yarn.lock b/extensions/vscode-colorize-tests/yarn.lock index b17b8b1954b..368b81f2f96 100644 --- a/extensions/vscode-colorize-tests/yarn.lock +++ b/extensions/vscode-colorize-tests/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^8.10.25": - version "8.10.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e" - integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA== +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== ajv@^5.1.0: version "5.3.0" diff --git a/extensions/vscode-test-resolver/.gitignore b/extensions/vscode-test-resolver/.gitignore new file mode 100644 index 00000000000..8e5962ee727 --- /dev/null +++ b/extensions/vscode-test-resolver/.gitignore @@ -0,0 +1,2 @@ +out +node_modules \ No newline at end of file diff --git a/extensions/vscode-test-resolver/.vscode/launch.json b/extensions/vscode-test-resolver/.vscode/launch.json new file mode 100644 index 00000000000..042a8d1fdd5 --- /dev/null +++ b/extensions/vscode-test-resolver/.vscode/launch.json @@ -0,0 +1,22 @@ +// A launch configuration that compiles the extension and then opens it inside a new window +// Use IntelliSense to learn about possible attributes. +// Hover to view descriptions of existing attributes. +// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Extension", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}", + "--remote=test+test" + ], + "outFiles": [ + "${workspaceFolder}/out/**/*.js" + ] + } + ] +} \ No newline at end of file diff --git a/extensions/vscode-test-resolver/.vscodeignore b/extensions/vscode-test-resolver/.vscodeignore new file mode 100644 index 00000000000..eb6a48615c7 --- /dev/null +++ b/extensions/vscode-test-resolver/.vscodeignore @@ -0,0 +1,6 @@ +.vscode/** +typings/** +**/*.ts +**/*.map +.gitignore +tsconfig.json diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json new file mode 100644 index 00000000000..0d93c4ea6d0 --- /dev/null +++ b/extensions/vscode-test-resolver/package.json @@ -0,0 +1,93 @@ +{ + "name": "vscode-test-resolver", + "description": "Test resolver for VS Code", + "version": "0.0.1", + "publisher": "vscode", + "enableProposedApi": true, + "private": true, + "engines": { + "vscode": "^1.25.0" + }, + "extensionKind": "ui", + "scripts": { + "compile": "node ./node_modules/vscode/bin/compile -watch -p ./", + "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-test-resolver ./tsconfig.json" + }, + "activationEvents": [ + "onResolveRemoteAuthority:test", + "onCommand:vscode-testresolver.newWindow", + "onCommand:vscode-testresolver.newWindowWithError", + "onCommand:vscode-testresolver.showLog" + ], + "main": "./out/extension", + "devDependencies": { + "@types/node": "^10.14.8", + "vscode": "1.1.5" + }, + "contributes": { + "resourceLabelFormatters": [ + { + "scheme": "vscode-remote", + "authority": "test+*", + "formatting": { + "label": "${path}", + "separator": "/", + "tildify": true, + "workspaceSuffix": "TestResolver" + } + } + ], + "commands": [ + { + "title": "New Window", + "category": "Remote-TestResolver", + "command": "vscode-testresolver.newWindow" + }, + { + "title": "Show Log", + "category": "Remote-TestResolver", + "command": "vscode-testresolver.showLog" + } + ], + "menus": { + "statusBar/windowIndicator": [ + { + "command": "vscode-testresolver.newWindow", + "when": "!remoteName", + "group": "9_local_testresolver@2" + }, + { + "command": "vscode-testresolver.showLog", + "when": "remoteName == test", + "group": "1_remote_testresolver_open@3" + }, + { + "command": "vscode-testresolver.newWindow", + "when": "remoteName == test", + "group": "1_remote_testresolver_open@1" + } + ] + }, + "configuration": { + "properties": { + "testresolver.startupDelay": { + "description": "If set, the resolver will delay for the given amount of seconds. Use ths setting for testing a slow resolver", + "type": "number", + "default": 0 + }, + "testresolver.startupError": { + "description": "If set, the resolver will fail. Use ths setting for testing the failure of a resolver.", + "type": "boolean", + "default": false + }, + "testresolver.pause": { + "description": "If set, connection is paused", + "type": "boolean", + "default": false + } + } + } + } + + +} \ No newline at end of file diff --git a/extensions/vscode-test-resolver/scripts/terminateProcess.sh b/extensions/vscode-test-resolver/scripts/terminateProcess.sh new file mode 100755 index 00000000000..908a68287fa --- /dev/null +++ b/extensions/vscode-test-resolver/scripts/terminateProcess.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +terminateTree() { + for cpid in $(/usr/bin/pgrep -P $1); do + terminateTree $cpid + done + kill -9 $1 > /dev/null 2>&1 +} + +for pid in $*; do + terminateTree $pid +done \ No newline at end of file diff --git a/extensions/vscode-test-resolver/src/download.ts b/extensions/vscode-test-resolver/src/download.ts new file mode 100644 index 00000000000..d94ea212237 --- /dev/null +++ b/extensions/vscode-test-resolver/src/download.ts @@ -0,0 +1,117 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as https from 'https'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as cp from 'child_process'; +import { parse as parseUrl } from 'url'; + +function ensureFolderExists(loc: string) { + if (!fs.existsSync(loc)) { + const parent = path.dirname(loc); + if (parent) { + ensureFolderExists(parent); + } + fs.mkdirSync(loc); + } +} + +function getDownloadUrl(updateUrl: string, commit: string, platform: string, quality: string): string { + return `${updateUrl}/commit:${commit}/server-${platform}/${quality}`; +} + +async function downloadVSCodeServerArchive(updateUrl: string, commit: string, quality: string, destDir: string): Promise { + ensureFolderExists(destDir); + + const platform = process.platform === 'win32' ? 'win32-x64' : process.platform === 'darwin' ? 'darwin' : 'linux-x64'; + const downloadUrl = getDownloadUrl(updateUrl, commit, platform, quality); + + return new Promise((resolve, reject) => { + console.log(`Downloading VS Code Server from: ${downloadUrl}`); + const requestOptions: https.RequestOptions = parseUrl(downloadUrl); + + https.get(requestOptions, res => { + if (res.statusCode !== 302) { + reject('Failed to get VS Code server archive location'); + } + const archiveUrl = res.headers.location; + if (!archiveUrl) { + reject('Failed to get VS Code server archive location'); + return; + } + + const archiveRequestOptions: https.RequestOptions = parseUrl(archiveUrl); + if (archiveUrl.endsWith('.zip')) { + const archivePath = path.resolve(destDir, `vscode-server-${commit}.zip`); + const outStream = fs.createWriteStream(archivePath); + outStream.on('close', () => { + resolve(archivePath); + }); + https.get(archiveRequestOptions, res => { + res.pipe(outStream); + }); + } else { + const zipPath = path.resolve(destDir, `vscode-server-${commit}.tgz`); + const outStream = fs.createWriteStream(zipPath); + https.get(archiveRequestOptions, res => { + res.pipe(outStream); + }); + outStream.on('close', () => { + resolve(zipPath); + }); + } + }); + }); +} + +/** + * Unzip a .zip or .tar.gz VS Code archive + */ +function unzipVSCodeServer(vscodeArchivePath: string, extractDir: string) { + if (vscodeArchivePath.endsWith('.zip')) { + const tempDir = fs.mkdtempSync('vscode-server'); + if (process.platform === 'win32') { + cp.spawnSync('powershell.exe', [ + '-NoProfile', + '-ExecutionPolicy', 'Bypass', + '-NonInteractive', + '-NoLogo', + '-Command', + `Microsoft.PowerShell.Archive\\Expand-Archive -Path "${vscodeArchivePath}" -DestinationPath "${tempDir}"` + ]); + } else { + cp.spawnSync('unzip', [vscodeArchivePath, '-d', `${tempDir}`]); + } + fs.renameSync(path.join(tempDir, process.platform === 'win32' ? 'vscode-server-win32-x64' : 'vscode-server-darwin'), extractDir); + } else { + // tar does not create extractDir by default + if (!fs.existsSync(extractDir)) { + fs.mkdirSync(extractDir); + } + cp.spawnSync('tar', ['-xzf', vscodeArchivePath, '-C', extractDir, '--strip-components', '1']); + } +} + +export async function downloadAndUnzipVSCodeServer(updateUrl: string, commit: string, quality: string = 'stable', destDir: string): Promise { + + const extractDir = path.join(destDir, commit); + if (fs.existsSync(extractDir)) { + console.log(`Found ${extractDir}. Skipping download.`); + } else { + console.log(`Downloading VS Code Server ${quality} - ${commit} into ${extractDir}.`); + try { + const vscodeArchivePath = await downloadVSCodeServerArchive(updateUrl, commit, quality, destDir); + if (fs.existsSync(vscodeArchivePath)) { + unzipVSCodeServer(vscodeArchivePath, extractDir); + // Remove archive + fs.unlinkSync(vscodeArchivePath); + } + } catch (err) { + throw Error(`Failed to download and unzip VS Code ${quality} - ${commit}`); + } + } + return Promise.resolve(extractDir); +} \ No newline at end of file diff --git a/extensions/vscode-test-resolver/src/extension.ts b/extensions/vscode-test-resolver/src/extension.ts new file mode 100644 index 00000000000..0520edcff4e --- /dev/null +++ b/extensions/vscode-test-resolver/src/extension.ts @@ -0,0 +1,284 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import * as cp from 'child_process'; +import * as path from 'path'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as net from 'net'; +import { downloadAndUnzipVSCodeServer } from './download'; +import { terminateProcess } from './util/processes'; + +let extHostProcess: cp.ChildProcess | undefined; +const enum CharCode { + Backspace = 8, + LineFeed = 10 +} + +let outputChannel: vscode.OutputChannel; + +export function activate(context: vscode.ExtensionContext) { + + function doResolve(_authority: string, progress: vscode.Progress<{ message?: string; increment?: number }>): Promise { + const serverPromise = new Promise(async (res, rej) => { + progress.report({ message: 'Starting Test Resolver' }); + outputChannel = vscode.window.createOutputChannel('TestResolver'); + + let isResolved = false; + async function processError(message: string) { + outputChannel.appendLine(message); + if (!isResolved) { + isResolved = true; + outputChannel.show(); + + const result = await vscode.window.showErrorMessage(message, { modal: true }, ...getActions()); + if (result) { + await result.execute(); + } + rej(vscode.RemoteAuthorityResolverError.NotAvailable(message, true)); + } + } + + let lastProgressLine = ''; + function processOutput(output: string) { + outputChannel.append(output); + for (let i = 0; i < output.length; i++) { + const chr = output.charCodeAt(i); + if (chr === CharCode.LineFeed) { + const match = lastProgressLine.match(/Extension host agent listening on (\d+)/); + if (match) { + isResolved = true; + res(new vscode.ResolvedAuthority('localhost', parseInt(match[1], 10))); // success! + } + lastProgressLine = ''; + } else if (chr === CharCode.Backspace) { + lastProgressLine = lastProgressLine.substr(0, lastProgressLine.length - 1); + } else { + lastProgressLine += output.charAt(i); + } + } + } + const delay = getConfiguration('startupDelay'); + if (typeof delay === 'number') { + let remaining = Math.ceil(delay); + outputChannel.append(`Delaying startup by ${remaining} seconds (configured by "testresolver.startupDelay").`); + while (remaining > 0) { + progress.report({ message: `Delayed resolving: Remaining ${remaining}s` }); + await (sleep(1000)); + remaining--; + } + } + + if (getConfiguration('startupError') === true) { + processError('Test Resolver failed for testing purposes (configured by "testresolver.startupError").'); + return; + } + + const { updateUrl, commit, quality, serverDataFolderName, dataFolderName } = getProductConfiguration(); + const serverCommand = process.platform === 'win32' ? 'server.bat' : 'server.sh'; + const commandArgs = ['--port=0', '--disable-telemetry']; + const env = getNewEnv(); + const remoteDataDir = process.env['TESTRESOLVER_DATA_FOLDER'] || path.join(os.homedir(), serverDataFolderName || `${dataFolderName}-testresolver`); + env['VSCODE_AGENT_FOLDER'] = remoteDataDir; + outputChannel.appendLine(`Using data folder at ${remoteDataDir}`); + + if (!commit) { // dev mode + const vscodePath = path.resolve(path.join(context.extensionPath, '..', '..')); + const serverCommandPath = path.join(vscodePath, 'resources', 'server', 'bin-dev', serverCommand); + extHostProcess = cp.spawn(serverCommandPath, commandArgs, { env, cwd: vscodePath }); + } else { + const serverBin = path.join(remoteDataDir, 'bin'); + progress.report({ message: 'Installing VSCode Server' }); + const serverLocation = await downloadAndUnzipVSCodeServer(updateUrl, commit, quality, serverBin); + outputChannel.appendLine(`Using server build at ${serverLocation}`); + + extHostProcess = cp.spawn(path.join(serverLocation, serverCommand), commandArgs, { env, cwd: serverLocation }); + } + extHostProcess.stdout.on('data', (data: Buffer) => processOutput(data.toString())); + extHostProcess.stderr.on('data', (data: Buffer) => processOutput(data.toString())); + extHostProcess.on('error', (error: Error) => { + processError(`server failed with error:\n${error.message}`); + extHostProcess = undefined; + }); + extHostProcess.on('close', (code: number) => { + processError(`server closed unexpectedly.\nError code: ${code}`); + extHostProcess = undefined; + }); + context.subscriptions.push({ + dispose: () => { + if (extHostProcess) { + terminateProcess(extHostProcess, context.extensionPath); + } + } + }); + }); + return serverPromise.then(serverAddr => { + return new Promise(async (res, _rej) => { + const proxyServer = net.createServer(proxySocket => { + outputChannel.appendLine(`Proxy connection accepted`); + let remoteReady = true, localReady = true; + const remoteSocket = net.createConnection({ port: serverAddr.port }); + + let isDisconnected = getConfiguration('pause') === true; + vscode.workspace.onDidChangeConfiguration(_ => { + let newIsDisconnected = getConfiguration('pause') === true; + if (isDisconnected !== newIsDisconnected) { + outputChannel.appendLine(`Connection state: ${newIsDisconnected ? 'open' : 'paused'}`); + isDisconnected = newIsDisconnected; + if (!isDisconnected) { + outputChannel.appendLine(`Resume remote and proxy sockets.`); + if (remoteSocket.isPaused() && localReady) { + remoteSocket.resume(); + } + if (proxySocket.isPaused() && remoteReady) { + proxySocket.resume(); + } + } else { + outputChannel.appendLine(`Pausing remote and proxy sockets.`); + if (!remoteSocket.isPaused()) { + remoteSocket.pause(); + } + if (!proxySocket.isPaused()) { + proxySocket.pause(); + } + } + } + }); + + proxySocket.on('data', (data) => { + remoteReady = remoteSocket.write(data); + if (!remoteReady) { + proxySocket.pause(); + } + }); + remoteSocket.on('data', (data) => { + localReady = proxySocket.write(data); + if (!localReady) { + remoteSocket.pause(); + } + }); + proxySocket.on('drain', () => { + localReady = true; + if (!isDisconnected) { + remoteSocket.resume(); + } + }); + remoteSocket.on('drain', () => { + remoteReady = true; + if (!isDisconnected) { + proxySocket.resume(); + } + }); + proxySocket.on('close', () => { + outputChannel.appendLine(`Proxy socket closed, closing remote socket.`); + remoteSocket.end(); + }); + remoteSocket.on('close', () => { + outputChannel.appendLine(`Remote socket closed, closing proxy socket.`); + proxySocket.end(); + }); + context.subscriptions.push({ + dispose: () => { + proxySocket.end(); + remoteSocket.end(); + } + }); + }); + proxyServer.listen(0, () => { + const port = (proxyServer.address()).port; + outputChannel.appendLine(`Going through proxy at port ${port}`); + res({ host: '127.0.0.1', port }); + }); + context.subscriptions.push({ + dispose: () => { + proxyServer.close(); + } + }); + }); + }); + } + + vscode.workspace.registerRemoteAuthorityResolver('test', { + resolve(_authority: string): Thenable { + return vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: 'Open TestResolver Remote ([details](command:remote-testresolver.showLog))', + cancellable: false + }, (progress) => doResolve(_authority, progress)); + } + }); + + vscode.commands.registerCommand('vscode-testresolver.newWindow', () => { + return vscode.commands.executeCommand('vscode.newWindow', { remoteAuthority: 'test+test' }); + }); + vscode.commands.registerCommand('vscode-testresolver.newWindowWithError', () => { + return vscode.commands.executeCommand('vscode.newWindow', { remoteAuthority: 'test+error' }); + }); + vscode.commands.registerCommand('vscode-testresolver.showLog', () => { + if (outputChannel) { + outputChannel.show(); + } + }); +} + +type ActionItem = (vscode.MessageItem & { execute: () => void; }); + +function getActions(): ActionItem[] { + const actions: ActionItem[] = []; + const isDirty = vscode.workspace.textDocuments.some(d => d.isDirty) || vscode.workspace.workspaceFile && vscode.workspace.workspaceFile.scheme === 'untitled'; + + actions.push({ + title: 'Retry', + execute: async () => { + await vscode.commands.executeCommand('workbench.action.reloadWindow'); + } + }); + if (!isDirty) { + actions.push({ + title: 'Close Remote', + execute: async () => { + await vscode.commands.executeCommand('vscode.newWindow', { reuseWindow: true }); + } + }); + } + actions.push({ + title: 'Ignore', + isCloseAffordance: true, + execute: async () => { + vscode.commands.executeCommand('vscode-testresolver.showLog'); // no need to wait + } + }); + return actions; +} + +export interface IProductConfiguration { + updateUrl: string; + commit: string; + quality: string; + dataFolderName: string; + serverDataFolderName?: string; +} + +function getProductConfiguration(): IProductConfiguration { + const content = fs.readFileSync(path.join(vscode.env.appRoot, 'product.json')).toString(); + return JSON.parse(content) as IProductConfiguration; +} + +function getNewEnv(): { [x: string]: string | undefined } { + const env = { ...process.env }; + delete env['ELECTRON_RUN_AS_NODE']; + return env; +} + +function sleep(ms: number): Promise { + return new Promise(resolve => { + setTimeout(resolve, ms); + }); +} + +function getConfiguration(id: string): T | undefined { + return vscode.workspace.getConfiguration('testresolver').get(id); +} diff --git a/src/typings/getmac.d.ts b/extensions/vscode-test-resolver/src/typings/ref.d.ts similarity index 69% rename from src/typings/getmac.d.ts rename to extensions/vscode-test-resolver/src/typings/ref.d.ts index e93b8135456..e3e47385d66 100644 --- a/src/typings/getmac.d.ts +++ b/extensions/vscode-test-resolver/src/typings/ref.d.ts @@ -3,10 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -declare module getmac { - export function getMac(callback: (error: Error, macAddress: string) => void): void; -} - -declare module 'getmac' { - export = getmac; -} \ No newline at end of file +/// +/// +/// diff --git a/extensions/vscode-test-resolver/src/util/processes.ts b/extensions/vscode-test-resolver/src/util/processes.ts new file mode 100644 index 00000000000..d5af12566fb --- /dev/null +++ b/extensions/vscode-test-resolver/src/util/processes.ts @@ -0,0 +1,37 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as cp from 'child_process'; +import * as path from 'path'; + +export interface TerminateResponse { + success: boolean; + error?: any; +} + +export function terminateProcess(p: cp.ChildProcess, extensionPath: string): TerminateResponse { + if (process.platform === 'win32') { + try { + const options: any = { + stdio: ['pipe', 'pipe', 'ignore'] + }; + cp.execFileSync('taskkill', ['/T', '/F', '/PID', p.pid.toString()], options); + } catch (err) { + return { success: false, error: err }; + } + } else if (process.platform === 'darwin' || process.platform === 'linux') { + try { + const cmd = path.join(extensionPath, 'scripts', 'terminateProcess.sh'); + const result = cp.spawnSync(cmd, [process.pid.toString()]); + if (result.error) { + return { success: false, error: result.error }; + } + } catch (err) { + return { success: false, error: err }; + } + } else { + p.kill('SIGKILL'); + } + return { success: true }; +} \ No newline at end of file diff --git a/extensions/vscode-test-resolver/tsconfig.json b/extensions/vscode-test-resolver/tsconfig.json new file mode 100644 index 00000000000..296ddb38fcb --- /dev/null +++ b/extensions/vscode-test-resolver/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../shared.tsconfig.json", + "compilerOptions": { + "outDir": "./out" + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file diff --git a/extensions/vscode-test-resolver/yarn.lock b/extensions/vscode-test-resolver/yarn.lock new file mode 100644 index 00000000000..925cef2c142 --- /dev/null +++ b/extensions/vscode-test-resolver/yarn.lock @@ -0,0 +1,1879 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/node@^10.14.8": + version "10.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9" + integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw== + +ajv@^6.5.5: + version "6.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" + integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-cyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" + integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= + dependencies: + ansi-wrap "0.1.0" + +ansi-gray@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= + dependencies: + ansi-wrap "0.1.0" + +ansi-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= + dependencies: + ansi-wrap "0.1.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-wrap@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= + +arr-diff@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" + integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= + dependencies: + arr-flatten "^1.0.1" + array-slice "^0.2.3" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" + integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= + +array-differ@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" + integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= + +array-slice@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" + integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1, array-uniq@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +beeper@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" + integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= + dependencies: + inherits "~2.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chalk@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +clone-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= + +clone-stats@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" + integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= + +clone-stats@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= + +clone@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" + integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8= + +clone@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +cloneable-readable@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" + integrity sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg== + dependencies: + inherits "^2.0.1" + process-nextick-args "^2.0.0" + readable-stream "^2.3.5" + +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" + integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== + dependencies: + delayed-stream "~1.0.0" + +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= + dependencies: + graceful-readlink ">= 1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +convert-source-map@^1.1.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" + integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== + dependencies: + safe-buffer "~5.1.1" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +dateformat@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" + integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= + +debug@2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw= + dependencies: + ms "2.0.0" + +deep-assign@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" + integrity sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s= + dependencies: + is-obj "^1.0.0" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +diff@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" + integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k= + +duplexer2@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" + integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= + dependencies: + readable-stream "~1.1.9" + +duplexer@^0.1.1, duplexer@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + +duplexify@^3.2.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +end-of-stream@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + dependencies: + once "^1.4.0" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +event-stream@3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= + dependencies: + duplexer "~0.1.1" + from "~0" + map-stream "~0.1.0" + pause-stream "0.0.11" + split "0.3" + stream-combiner "~0.0.4" + through "~2.3.1" + +event-stream@^3.3.1, event-stream@~3.3.4: + version "3.3.5" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.5.tgz#e5dd8989543630d94c6cf4d657120341fa31636b" + integrity sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g== + dependencies: + duplexer "^0.1.1" + from "^0.1.7" + map-stream "0.0.7" + pause-stream "^0.0.11" + split "^1.0.1" + stream-combiner "^0.2.2" + through "^2.3.8" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= + dependencies: + fill-range "^2.1.0" + +extend-shallow@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" + integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= + dependencies: + kind-of "^1.1.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend@^3.0.0, extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= + dependencies: + is-extglob "^1.0.0" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fancy-log@^1.1.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" + integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== + dependencies: + ansi-gray "^0.1.1" + color-support "^1.1.3" + parse-node-version "^1.0.0" + time-stamp "^1.0.0" + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= + +fill-range@^2.1.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^3.0.0" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +first-chunk-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" + integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04= + +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= + dependencies: + for-in "^1.0.1" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +from@^0.1.7, from@~0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" + integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fstream@^1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= + dependencies: + is-glob "^2.0.0" + +glob-parent@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-stream@^5.3.2: + version "5.3.5" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" + integrity sha1-pVZlqajM3EGRWofHAeMtTgFvrSI= + dependencies: + extend "^3.0.0" + glob "^5.0.3" + glob-parent "^3.0.0" + micromatch "^2.3.7" + ordered-read-streams "^0.3.0" + through2 "^0.6.0" + to-absolute-glob "^0.1.1" + unique-stream "^2.0.2" + +glob@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg= + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^5.0.3: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.1, glob@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glogg@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" + integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== + dependencies: + sparkles "^1.0.0" + +graceful-fs@^4.0.0, graceful-fs@^4.1.2: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8= + +gulp-chmod@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/gulp-chmod/-/gulp-chmod-2.0.0.tgz#00c390b928a0799b251accf631aa09e01cc6299c" + integrity sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw= + dependencies: + deep-assign "^1.0.0" + stat-mode "^0.2.0" + through2 "^2.0.0" + +gulp-filter@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-5.1.0.tgz#a05e11affb07cf7dcf41a7de1cb7b63ac3783e73" + integrity sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM= + dependencies: + multimatch "^2.0.0" + plugin-error "^0.1.2" + streamfilter "^1.0.5" + +gulp-gunzip@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/gulp-gunzip/-/gulp-gunzip-0.0.3.tgz#7b6e07b0f58fd3d42515c48ead5a63df0572f62f" + integrity sha1-e24HsPWP09QlFcSOrVpj3wVy9i8= + dependencies: + through2 "~0.6.5" + vinyl "~0.4.6" + +gulp-remote-src@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/gulp-remote-src/-/gulp-remote-src-0.4.4.tgz#4a4d18fac0ffedde94a7855953de90db00a1d1b1" + integrity sha512-mo7lGgZmNXyTbcUzfjSnUVkx1pnqqiwv/pPaIrYdTO77hq0WNTxXLAzQdoYOnyJ0mfVLNmNl9AGqWLiAzTPMMA== + dependencies: + event-stream "3.3.4" + node.extend "~1.1.2" + request "^2.88.0" + through2 "~2.0.3" + vinyl "~2.0.1" + +gulp-sourcemaps@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" + integrity sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw= + dependencies: + convert-source-map "^1.1.1" + graceful-fs "^4.1.2" + strip-bom "^2.0.0" + through2 "^2.0.0" + vinyl "^1.0.0" + +gulp-symdest@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/gulp-symdest/-/gulp-symdest-1.1.1.tgz#b0a6df3d43a0537165946ab8e38c1b7080a66fac" + integrity sha512-UHd3MokfIN7SrFdsbV5uZTwzBpL0ZSTu7iq98fuDqBGZ0dlHxgbQBJwfd6qjCW83snkQ3Hz9IY4sMRMz2iTq7w== + dependencies: + event-stream "3.3.4" + mkdirp "^0.5.1" + queue "^3.1.0" + vinyl-fs "^2.4.3" + +gulp-untar@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.6.tgz#d6bdefde7e9a8e054c9f162385a0782c4be74000" + integrity sha1-1r3v3n6ajgVMnxYjhaB4LEvnQAA= + dependencies: + event-stream "~3.3.4" + gulp-util "~3.0.8" + streamifier "~0.1.1" + tar "^2.2.1" + through2 "~2.0.3" + +gulp-util@~3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" + integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= + dependencies: + array-differ "^1.0.0" + array-uniq "^1.0.2" + beeper "^1.0.0" + chalk "^1.0.0" + dateformat "^2.0.0" + fancy-log "^1.1.0" + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash._reescape "^3.0.0" + lodash._reevaluate "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.template "^3.0.0" + minimist "^1.1.0" + multipipe "^0.1.2" + object-assign "^3.0.0" + replace-ext "0.0.1" + through2 "^2.0.0" + vinyl "^0.5.0" + +gulp-vinyl-zip@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/gulp-vinyl-zip/-/gulp-vinyl-zip-1.4.0.tgz#56382f2ccb57231bb0478c78737ccd572973bee1" + integrity sha1-VjgvLMtXIxuwR4x4c3zNVylzvuE= + dependencies: + event-stream "^3.3.1" + queue "^3.0.10" + through2 "^0.6.3" + vinyl "^0.4.6" + vinyl-fs "^2.0.0" + yauzl "^2.2.1" + yazl "^2.2.1" + +gulplog@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= + dependencies: + glogg "^1.0.0" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + +has-gulplog@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" + integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= + dependencies: + sparkles "^1.0.0" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= + +is-extglob@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= + dependencies: + is-extglob "^1.0.0" + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= + dependencies: + kind-of "^3.0.2" + +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= + +is-stream@^1.0.1, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-valid-glob@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" + integrity sha1-1LVcafUYhvm2XHDWwmItN+KfSP4= + +is@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79" + integrity sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +kind-of@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" + integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +lazystream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" + integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= + dependencies: + readable-stream "^2.0.5" + +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + integrity sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4= + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= + +lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" + integrity sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE= + +lodash._basetostring@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" + integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= + +lodash._basevalues@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" + integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= + +lodash._reescape@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" + integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= + +lodash._reevaluate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" + integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + +lodash._root@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= + +lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" + integrity sha1-1/KEnw29p+BGgruM1yqwIkYd6+c= + dependencies: + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" + +lodash.escape@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" + integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= + dependencies: + lodash._root "^3.0.0" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= + +lodash.isequal@^4.0.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash.restparam@^3.0.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= + +lodash.template@^3.0.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" + integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= + dependencies: + lodash._basecopy "^3.0.0" + lodash._basetostring "^3.0.0" + lodash._basevalues "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + lodash.keys "^3.0.0" + lodash.restparam "^3.0.0" + lodash.templatesettings "^3.0.0" + +lodash.templatesettings@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" + integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + +map-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" + integrity sha1-ih8HiW2CsQkmvTdEokIACfiJdKg= + +map-stream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" + integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= + +math-random@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" + integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== + +merge-stream@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" + integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= + dependencies: + readable-stream "^2.0.1" + +micromatch@^2.3.7: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +mime-db@~1.38.0: + version "1.38.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" + integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.22" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" + integrity sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog== + dependencies: + mime-db "~1.38.0" + +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mocha@^3.2.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" + integrity sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg== + dependencies: + browser-stdout "1.3.0" + commander "2.9.0" + debug "2.6.8" + diff "3.2.0" + escape-string-regexp "1.0.5" + glob "7.1.1" + growl "1.9.2" + he "1.1.1" + json3 "3.3.2" + lodash.create "3.1.1" + mkdirp "0.5.1" + supports-color "3.1.2" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +multimatch@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" + integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= + dependencies: + array-differ "^1.0.0" + array-union "^1.0.1" + arrify "^1.0.0" + minimatch "^3.0.0" + +multipipe@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" + integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= + dependencies: + duplexer2 "0.0.2" + +node.extend@~1.1.2: + version "1.1.8" + resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.8.tgz#0aab3e63789f4e6d68b42bc00073ad1881243cf0" + integrity sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA== + dependencies: + has "^1.0.3" + is "^3.2.1" + +normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" + integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= + +object-assign@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +once@^1.3.0, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +ordered-read-streams@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" + integrity sha1-cTfmmzKYuzQiR6G77jiByA4v14s= + dependencies: + is-stream "^1.0.1" + readable-stream "^2.0.1" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-node-version@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" + integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +pause-stream@0.0.11, pause-stream@^0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= + dependencies: + through "~2.3" + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +plugin-error@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" + integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= + dependencies: + ansi-cyan "^0.1.1" + ansi-red "^0.1.1" + arr-diff "^1.0.1" + arr-union "^2.0.1" + extend-shallow "^1.1.2" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= + +process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + +psl@^1.1.24: + version "1.1.31" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" + integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +querystringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.0.tgz#7ded8dfbf7879dcc60d0a644ac6754b283ad17ef" + integrity sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg== + +queue@^3.0.10, queue@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/queue/-/queue-3.1.0.tgz#6c49d01f009e2256788789f2bffac6b8b9990585" + integrity sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU= + dependencies: + inherits "~2.0.0" + +randomatic@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" + integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" + +"readable-stream@>=1.0.33-1 <1.1.0-0": + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.3.5, readable-stream@~2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== + dependencies: + is-equal-shallow "^0.1.3" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +replace-ext@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" + integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= + +replace-ext@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + +request@^2.79.0, request@^2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +rimraf@2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^5.3.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== + +source-map-support@^0.4.11: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +sparkles@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" + integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== + +split@0.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" + integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= + dependencies: + through "2" + +split@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== + dependencies: + through "2" + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stat-mode@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" + integrity sha1-5sgLYjEj19gM8TLOU480YokHJQI= + +stream-combiner@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858" + integrity sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg= + dependencies: + duplexer "~0.1.1" + through "~2.3.4" + +stream-combiner@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" + integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= + dependencies: + duplexer "~0.1.1" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + +streamfilter@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.7.tgz#ae3e64522aa5a35c061fd17f67620c7653c643c9" + integrity sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ== + dependencies: + readable-stream "^2.0.2" + +streamifier@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" + integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-bom-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" + integrity sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4= + dependencies: + first-chunk-stream "^1.0.0" + strip-bom "^2.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + dependencies: + is-utf8 "^0.2.0" + +supports-color@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + integrity sha1-cqJiiU2dQIuVbKBf83su2KbiotU= + dependencies: + has-flag "^1.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +tar@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +through2-filter@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" + integrity sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw= + dependencies: + through2 "~2.0.0" + xtend "~4.0.0" + +through2-filter@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" + integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== + dependencies: + through2 "~2.0.0" + xtend "~4.0.0" + +through2@^0.6.0, through2@^0.6.3, through2@~0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" + integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= + dependencies: + readable-stream ">=1.0.33-1 <1.1.0-0" + xtend ">=4.0.0 <4.1.0-0" + +through2@^2.0.0, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through@2, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +time-stamp@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= + +to-absolute-glob@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" + integrity sha1-HN+kcqnvUMI57maZm2YsoOs5k38= + dependencies: + extend-shallow "^2.0.1" + +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +unique-stream@^2.0.2: + version "2.3.1" + resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" + integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== + dependencies: + json-stable-stringify-without-jsonify "^1.0.1" + through2-filter "^3.0.0" + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +url-parse@^1.1.9: + version "1.4.4" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8" + integrity sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg== + dependencies: + querystringify "^2.0.0" + requires-port "^1.0.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +vali-date@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" + integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vinyl-fs@^2.0.0, vinyl-fs@^2.4.3: + version "2.4.4" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" + integrity sha1-vm/zJwy1Xf19MGNkDegfJddTIjk= + dependencies: + duplexify "^3.2.0" + glob-stream "^5.3.2" + graceful-fs "^4.0.0" + gulp-sourcemaps "1.6.0" + is-valid-glob "^0.3.0" + lazystream "^1.0.0" + lodash.isequal "^4.0.0" + merge-stream "^1.0.0" + mkdirp "^0.5.0" + object-assign "^4.0.0" + readable-stream "^2.0.4" + strip-bom "^2.0.0" + strip-bom-stream "^1.0.0" + through2 "^2.0.0" + through2-filter "^2.0.0" + vali-date "^1.0.0" + vinyl "^1.0.0" + +vinyl-source-stream@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz#62b53a135610a896e98ca96bee3a87f008a8e780" + integrity sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A= + dependencies: + through2 "^2.0.3" + vinyl "^0.4.3" + +vinyl@^0.4.3, vinyl@^0.4.6, vinyl@~0.4.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" + integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc= + dependencies: + clone "^0.2.0" + clone-stats "^0.0.1" + +vinyl@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" + integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + +vinyl@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" + integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + +vinyl@~2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.0.2.tgz#0a3713d8d4e9221c58f10ca16c0116c9e25eda7c" + integrity sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw= + dependencies: + clone "^1.0.0" + clone-buffer "^1.0.0" + clone-stats "^1.0.0" + cloneable-readable "^1.0.0" + is-stream "^1.1.0" + remove-trailing-separator "^1.0.1" + replace-ext "^1.0.0" + +vscode@1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.5.tgz#10eb104001840c3dd0813815fd4a05f8fc882d14" + integrity sha1-EOsQQAGEDD3QgTgV/UoF+PyILRQ= + dependencies: + glob "^7.1.1" + gulp-chmod "^2.0.0" + gulp-filter "^5.0.0" + gulp-gunzip "0.0.3" + gulp-remote-src "^0.4.2" + gulp-symdest "^1.1.0" + gulp-untar "^0.0.6" + gulp-vinyl-zip "^1.4.0" + mocha "^3.2.0" + request "^2.79.0" + semver "^5.3.0" + source-map-support "^0.4.11" + url-parse "^1.1.9" + vinyl-source-stream "^1.1.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +"xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.0, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + +yauzl@^2.2.1: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + +yazl@^2.2.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" + integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw== + dependencies: + buffer-crc32 "~0.2.3" diff --git a/extensions/xml/package.json b/extensions/xml/package.json index 985266edf90..d76a632b10c 100644 --- a/extensions/xml/package.json +++ b/extensions/xml/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, "contributes": { "languages": [{ @@ -22,6 +23,8 @@ ".dita", ".ditamap", ".dtd", + ".ent", + ".mod", ".dtml", ".fsproj", ".fxml", diff --git a/extensions/xml/xml.language-configuration.json b/extensions/xml/xml.language-configuration.json index faaa59c1cd3..702b6dc6eb7 100644 --- a/extensions/xml/xml.language-configuration.json +++ b/extensions/xml/xml.language-configuration.json @@ -1,31 +1,34 @@ { "comments": { - "lineComment": "", - "blockComment": [""] + "blockComment": [ "" ] }, "brackets": [ - ["<", ">"] + [""], + ["<", ">"], + ["{", "}"], + ["(", ")"] ], "autoClosingPairs": [ - ["<", ">"], - ["'", "'"], - ["\"", "\""] + { "open": "{", "close": "}"}, + { "open": "[", "close": "]"}, + { "open": "(", "close": ")" }, + { "open": "'", "close": "'" }, + { "open": "\"", "close": "\"" }, + { "open": "", "notIn": [ "comment", "string" ]}, + { "open": "", "notIn": [ "comment", "string" ]} ], "surroundingPairs": [ - ["<", ">"], - ["'", "'"], - ["\"", "\""] - ] - - // enhancedBrackets: [{ - // tokenType: 'tag.tag-$1.xml', - // openTrigger: '>', - // open: /<(\w[\w\d]*)([^\/>]*(?!\/)>)[^<>]*$/i, - // closeComplete: '', - // closeTrigger: '>', - // close: /<\/(\w[\w\d]*)\s*>$/i - // }], - - // autoClosingPairs: [['\'', '\''], ['"', '"'] ] - + { "open": "'", "close": "'" }, + { "open": "\"", "close": "\"" }, + { "open": "{", "close": "}"}, + { "open": "[", "close": "]"}, + { "open": "(", "close": ")" }, + { "open": "<", "close": ">" } + ], + "folding": { + "markers": { + "start": "^\\s*", + "end": "^\\s*" + } + } } diff --git a/extensions/yaml/.gitignore b/extensions/yaml/.gitignore deleted file mode 100644 index 3c3629e647f..00000000000 --- a/extensions/yaml/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/extensions/yaml/cgmanifest.json b/extensions/yaml/cgmanifest.json index 80ba8ae522c..e6c3ca158b5 100644 --- a/extensions/yaml/cgmanifest.json +++ b/extensions/yaml/cgmanifest.json @@ -34,4 +34,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/yaml/package.json b/extensions/yaml/package.json index 79e2eecc316..5b12e0fbc5b 100644 --- a/extensions/yaml/package.json +++ b/extensions/yaml/package.json @@ -4,6 +4,7 @@ "description": "%description%", "version": "1.0.0", "publisher": "vscode", + "license": "MIT", "engines": { "vscode": "*" }, diff --git a/extensions/yarn.lock b/extensions/yarn.lock index 4e2a9131776..8e552194c13 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -typescript@3.3.0-dev.20190101: - version "3.3.0-dev.20190101" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.0-dev.20190101.tgz#2eecb7a9c6c63d447615b6e6b2d6e648cfdc4caa" - integrity sha512-pmpqjyS64DIfnCJ8XGFXlTC+g3hCud69EYEudjS/alwlVx2qedQedY36ASHPRopiZxJcwHCkM/CypDiQtfQZVw== +typescript@3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.2.tgz#a09e1dc69bc9551cadf17dba10ee42cf55e5d56c" + integrity sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA== diff --git a/gulpfile.js b/gulpfile.js index fe899377d79..8a5eff502f6 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -10,31 +10,27 @@ require('events').EventEmitter.defaultMaxListeners = 100; const gulp = require('gulp'); const util = require('./build/lib/util'); +const task = require('./build/lib/task'); const path = require('path'); const compilation = require('./build/lib/compilation'); +const { monacoTypecheckTask/* , monacoTypecheckWatchTask */ } = require('./build/gulpfile.editor'); +const { compileExtensionsTask, watchExtensionsTask } = require('./build/gulpfile.extensions'); // Fast compile for development time -gulp.task('clean-client', util.rimraf('out')); -gulp.task('compile-client', ['clean-client'], compilation.compileTask('src', 'out', false)); -gulp.task('watch-client', ['clean-client'], compilation.watchTask('out', false)); +const compileClientTask = task.define('compile-client', task.series(util.rimraf('out'), compilation.compileTask('src', 'out', false))); +gulp.task(compileClientTask); -// Full compile, including nls and inline sources in sourcemaps, for build -gulp.task('clean-client-build', util.rimraf('out-build')); -gulp.task('compile-client-build', ['clean-client-build'], compilation.compileTask('src', 'out-build', true)); -gulp.task('watch-client-build', ['clean-client-build'], compilation.watchTask('out-build', true)); - -// Default -gulp.task('default', ['compile']); +const watchClientTask = task.define('watch-client', task.series(util.rimraf('out'), compilation.watchTask('out', false))); +gulp.task(watchClientTask); // All -gulp.task('clean', ['clean-client', 'clean-extensions']); -gulp.task('compile', ['monaco-typecheck', 'compile-client', 'compile-extensions']); -gulp.task('watch', [/* 'monaco-typecheck-watch', */ 'watch-client', 'watch-extensions']); +const compileTask = task.define('compile', task.parallel(monacoTypecheckTask, compileClientTask, compileExtensionsTask)); +gulp.task(compileTask); -// All Build -gulp.task('clean-build', ['clean-client-build', 'clean-extensions-build']); -gulp.task('compile-build', ['compile-client-build', 'compile-extensions-build']); -gulp.task('watch-build', ['watch-client-build', 'watch-extensions-build']); +gulp.task(task.define('watch', task.parallel(/* monacoTypecheckWatchTask, */ watchClientTask, watchExtensionsTask))); + +// Default +gulp.task('default', compileTask); process.on('unhandledRejection', (reason, p) => { console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); @@ -44,4 +40,4 @@ process.on('unhandledRejection', (reason, p) => { // Load all the gulpfiles only if running tasks other than the editor tasks const build = path.join(__dirname, 'build'); require('glob').sync('gulpfile.*.js', { cwd: build }) - .forEach(f => require(`./build/${f}`)); + .forEach(f => require(`./build/${f}`)); \ No newline at end of file diff --git a/package.json b/package.json index 90320567c03..f2113d68da9 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,11 @@ { "name": "code-oss-dev", - "version": "1.31.0", - "distro": "455b23e66edb0fb17a1d7f5764ff35eec7c1b2d1", + "version": "1.38.0", + "distro": "f123663d79c57c07e3f70b2d0938f1a58ff4d1da", "author": { "name": "Microsoft Corporation" }, + "license": "MIT", "main": "./out/main", "private": true, "scripts": { @@ -16,96 +17,100 @@ "watch-client": "gulp watch-client --max_old_space_size=4095", "monaco-editor-test": "mocha --only-monaco-editor", "precommit": "node build/gulpfile.hygiene.js", - "gulp": "gulp --max_old_space_size=4095", + "gulp": "gulp --max_old_space_size=8192", "7z": "7z", "update-grammars": "node build/npm/update-all-grammars.js", "update-localization-extension": "node build/npm/update-localization-extension.js", "smoketest": "cd test/smoke && node test/index.js", - "monaco-compile-check": "tsc -p src/tsconfig.monaco.json --noEmit", "download-builtin-extensions": "node build/lib/builtInExtensions.js", - "strict-null-check": "tsc -p src/tsconfig.strictNullChecks.json", - "strict-null-check-watch": "tsc -p src/tsconfig.strictNullChecks.json --watch" + "monaco-compile-check": "tsc -p src/tsconfig.monaco.json --noEmit", + "strict-initialization-watch": "tsc --watch -p src/tsconfig.json --noEmit --strictPropertyInitialization", + "update-distro": "node build/npm/update-distro.js" }, "dependencies": { - "applicationinsights": "1.0.7", - "fast-plist": "0.1.2", - "gc-signals": "^0.0.1", - "getmac": "1.4.1", + "applicationinsights": "1.0.8", "graceful-fs": "4.1.11", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.1", - "iconv-lite": "0.4.23", + "iconv-lite": "0.5.0", "jschardet": "1.6.0", - "keytar": "4.2.1", - "minimist": "1.2.0", - "native-is-elevated": "^0.2.1", - "native-keymap": "1.2.5", + "keytar": "^4.11.0", + "native-is-elevated": "0.3.0", + "native-keymap": "2.0.0", "native-watchdog": "1.0.0", - "node-pty": "0.8.0", - "semver": "^5.5.0", - "spdlog": "0.7.2", - "sudo-prompt": "8.2.0", + "node-pty": "0.9.0-beta19", + "nsfw": "1.2.5", + "onigasm-umd": "^2.2.2", + "semver-umd": "^5.5.3", + "spdlog": "^0.9.0", + "sudo-prompt": "9.0.0", "v8-inspect-profiler": "^0.0.20", - "vscode-chokidar": "1.6.5", - "vscode-debugprotocol": "1.33.0", - "vscode-nsfw": "1.1.1", - "vscode-proxy-agent": "0.2.0", - "vscode-ripgrep": "^1.2.5", - "vscode-sqlite3": "4.0.5", - "vscode-textmate": "^4.0.1", - "vscode-xterm": "3.10.0-beta10-reflow", - "winreg": "^1.2.4", - "yauzl": "^2.9.1", + "vscode-chokidar": "2.1.7", + "vscode-minimist": "^1.2.1", + "vscode-proxy-agent": "0.4.0", + "vscode-ripgrep": "^1.5.5", + "vscode-sqlite3": "4.0.8", + "vscode-textmate": "^4.2.2", + "xterm": "3.15.0-beta90", + "xterm-addon-search": "0.2.0-beta3", + "xterm-addon-web-links": "0.1.0-beta10", + "yauzl": "^2.9.2", "yazl": "^2.4.3" }, "devDependencies": { "7zip": "0.0.6", - "@types/keytar": "^4.0.1", - "@types/minimist": "^1.2.0", + "@types/keytar": "^4.4.0", "@types/mocha": "2.2.39", "@types/node": "^10.12.12", "@types/semver": "^5.5.0", "@types/sinon": "^1.16.36", "@types/webpack": "^4.4.10", "@types/winreg": "^1.2.30", + "ansi-colors": "^3.2.3", "asar": "^0.14.0", "chromium-pickle-js": "^0.2.0", - "clean-css": "3.4.6", "copy-webpack-plugin": "^4.5.2", "coveralls": "^2.11.11", "cson-parser": "^1.3.3", "debounce": "^1.0.0", "documentdb": "^1.5.1", "electron-mksnapshot": "~2.0.0", - "eslint": "^3.4.0", + "eslint": "^4.18.2", "event-stream": "3.3.4", "express": "^4.13.1", + "fancy-log": "^1.3.3", + "fast-plist": "0.1.2", "glob": "^5.0.13", - "gulp": "^3.8.9", - "gulp-atom-electron": "^1.19.2", - "gulp-azure-storage": "^0.8.2", + "gulp": "^4.0.0", + "gulp-atom-electron": "^1.21.1", + "gulp-azure-storage": "^0.10.0", "gulp-buffer": "0.0.2", - "gulp-concat": "^2.6.0", - "gulp-cssnano": "^2.1.0", - "gulp-eslint": "^3.0.1", - "gulp-filter": "^3.0.0", - "gulp-flatmap": "^1.0.0", - "gulp-json-editor": "^2.2.1", - "gulp-mocha": "^2.1.3", + "gulp-concat": "^2.6.1", + "gulp-cssnano": "^2.1.3", + "gulp-eslint": "^5.0.0", + "gulp-filter": "^5.1.0", + "gulp-flatmap": "^1.0.2", + "gulp-gunzip": "^1.0.0", + "gulp-json-editor": "^2.5.0", "gulp-plumber": "^1.2.0", - "gulp-remote-src": "^0.4.4", + "gulp-remote-retry-src": "^0.6.0", "gulp-rename": "^1.2.0", "gulp-replace": "^0.5.4", - "gulp-shell": "^0.5.2", - "gulp-tsb": "2.0.5", - "gulp-tslint": "^8.1.2", + "gulp-shell": "^0.6.5", + "gulp-tsb": "2.0.7", + "gulp-tslint": "^8.1.3", "gulp-uglify": "^3.0.0", - "gulp-util": "^3.0.6", + "gulp-untar": "^0.0.7", "gulp-vinyl-zip": "^2.1.2", + "http-server": "^0.11.1", "husky": "^0.13.1", - "innosetup-compiler": "^5.5.60", + "innosetup": "5.6.1", "is": "^3.1.0", - "istanbul": "^0.3.17", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.6", "jsdom-no-contextify": "^3.1.0", "lazy.js": "^0.4.2", "merge-options": "^1.0.1", @@ -114,26 +119,26 @@ "mkdirp": "^0.5.0", "mocha": "^2.2.5", "mocha-junit-reporter": "^1.17.0", + "opn": "^5.4.0", "optimist": "0.3.5", "p-all": "^1.0.0", "pump": "^1.0.1", "queue": "3.0.6", "rcedit": "^1.1.0", - "remap-istanbul": "^0.6.4", "rimraf": "^2.2.8", "sinon": "^1.17.2", "source-map": "^0.4.4", "ts-loader": "^4.4.2", - "tslint": "^5.11.0", - "typescript": "3.2.2", + "tslint": "^5.16.0", + "typescript": "3.5.2", "typescript-formatter": "7.1.0", - "typescript-tslint-plugin": "^0.0.7", "uglify-es": "^3.0.18", "underscore": "^1.8.2", - "vinyl": "^0.4.5", - "vinyl-fs": "^2.4.3", + "vinyl": "^2.0.0", + "vinyl-fs": "^3.0.0", "vsce": "1.48.0", - "vscode-nls-dev": "3.2.2", + "vscode-debugprotocol": "1.35.0", + "vscode-nls-dev": "^3.3.1", "webpack": "^4.16.5", "webpack-cli": "^3.1.0", "webpack-stream": "^5.1.1" @@ -146,8 +151,10 @@ "url": "https://github.com/Microsoft/vscode/issues" }, "optionalDependencies": { - "windows-foreground-love": "0.1.0", - "windows-mutex": "0.2.1", - "windows-process-tree": "0.2.3" + "vscode-windows-ca-certs": "0.1.0", + "vscode-windows-registry": "1.0.2", + "windows-foreground-love": "0.2.0", + "windows-mutex": "0.3.0", + "windows-process-tree": "0.2.4" } } diff --git a/product.json b/product.json index eb6526c2d8f..4103352af85 100644 --- a/product.json +++ b/product.json @@ -16,9 +16,11 @@ "win32AppUserModelId": "Microsoft.CodeOSS", "win32ShellNameShort": "C&ode - OSS", "darwinBundleIdentifier": "com.visualstudio.code.oss", + "linuxIconName": "com.visualstudio.code.oss", + "licenseFileName": "LICENSE.txt", "reportIssueUrl": "https://github.com/Microsoft/vscode/issues/new", "urlProtocol": "code-oss", "extensionAllowedProposedApi": [ "ms-vscode.references-view" ] -} +} \ No newline at end of file diff --git a/remote/.yarnrc b/remote/.yarnrc new file mode 100644 index 00000000000..b28191e6bae --- /dev/null +++ b/remote/.yarnrc @@ -0,0 +1,3 @@ +disturl "http://nodejs.org/dist" +target "10.11.0" +runtime "node" diff --git a/remote/package.json b/remote/package.json new file mode 100644 index 00000000000..5f851213c9d --- /dev/null +++ b/remote/package.json @@ -0,0 +1,33 @@ +{ + "name": "vscode-reh", + "version": "0.0.0", + "dependencies": { + "applicationinsights": "1.0.8", + "getmac": "1.4.1", + "graceful-fs": "4.1.11", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "iconv-lite": "0.5.0", + "jschardet": "1.6.0", + "minimist": "1.2.0", + "native-watchdog": "1.0.0", + "node-pty": "0.9.0-beta19", + "nsfw": "1.2.5", + "onigasm-umd": "^2.2.2", + "semver-umd": "^5.5.3", + "spdlog": "^0.9.0", + "vscode-chokidar": "2.1.7", + "vscode-proxy-agent": "0.4.0", + "vscode-ripgrep": "^1.5.5", + "vscode-textmate": "^4.2.2", + "xterm": "3.15.0-beta90", + "xterm-addon-search": "0.2.0-beta3", + "xterm-addon-web-links": "0.1.0-beta10", + "yauzl": "^2.9.2", + "yazl": "^2.4.3" + }, + "optionalDependencies": { + "vscode-windows-ca-certs": "0.1.0", + "vscode-windows-registry": "1.0.1" + } +} diff --git a/remote/web/.yarnrc b/remote/web/.yarnrc new file mode 100644 index 00000000000..b28191e6bae --- /dev/null +++ b/remote/web/.yarnrc @@ -0,0 +1,3 @@ +disturl "http://nodejs.org/dist" +target "10.11.0" +runtime "node" diff --git a/remote/web/package.json b/remote/web/package.json new file mode 100644 index 00000000000..c7a487b6c2d --- /dev/null +++ b/remote/web/package.json @@ -0,0 +1,12 @@ +{ + "name": "vscode-web", + "version": "0.0.0", + "dependencies": { + "onigasm-umd": "^2.2.2", + "vscode-textmate": "^4.1.1", + "xterm": "3.15.0-beta67", + "xterm-addon-search": "0.2.0-beta2", + "xterm-addon-web-links": "0.1.0-beta10", + "semver-umd": "^5.5.3" + } + } \ No newline at end of file diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock new file mode 100644 index 00000000000..b624eb37290 --- /dev/null +++ b/remote/web/yarn.lock @@ -0,0 +1,47 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +nan@^2.14.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + +onigasm-umd@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/onigasm-umd/-/onigasm-umd-2.2.2.tgz#b989d762df61f899a3052ac794a50bd93fe20257" + integrity sha512-v2eMOJu7iE444L2iJN+U6s6s5S0y7oj/N0DAkrd6wokRtTVoq/v/yaDI1lIqFrTeJbNtqNzYvguDF5yNzW3Rvw== + +oniguruma@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/oniguruma/-/oniguruma-7.2.0.tgz#c9a59c1ea7b9fe67e237a02e02139b638856f3af" + integrity sha512-bh+ZLdykY1sdIx8jBp2zpLbVFDBc3XmKH4Ceo2lijNaN1WhEqtnpqFlmtCbRuDB17nJ58RAUStVwfW8e8uEbnA== + dependencies: + nan "^2.14.0" + +semver-umd@^5.5.3: + version "5.5.3" + resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.3.tgz#b64d7a2d4f5a717b369d56e31940a38e47e34d1e" + integrity sha512-HOnQrn2iKnVe/xlqCTzMXQdvSz3rPbD0DmQXYuQ+oK1dpptGFfPghonQrx5JHl2O7EJwDqtQnjhE7ME23q6ngw== + +vscode-textmate@^4.1.1: + version "4.2.2" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.2.2.tgz#0b4dabc69a6fba79a065cb6b615f66eac07c8f4c" + integrity sha512-1U4ih0E/KP1zNK/EbpUqyYtI7PY+Ccd2nDGTtiMR/UalLFnmaYkwoWhN1oI7B91ptBN8NdVwWuvyUnvJAulCUw== + dependencies: + oniguruma "^7.2.0" + +xterm-addon-search@0.2.0-beta2: + version "0.2.0-beta2" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.2.0-beta2.tgz#c3173f0a6f207ee9f1848849174ee5d6b6ce8262" + integrity sha512-XEcwi2TeFGk2MuIFjiI/OpVXSNO5dGQBvHH3o+9KzqG3ooVqhhDqzwxs092QGNcNCGh8hGn/PWZiczaBBnKm/g== + +xterm-addon-web-links@0.1.0-beta10: + version "0.1.0-beta10" + resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.1.0-beta10.tgz#610fa9773a2a5ccd41c1c83ba0e2dd2c9eb66a23" + integrity sha512-xfpjy0V6bB4BR44qIgZQPoCMVakxb65gMscPkHpO//QxvUxKzabV3dxOsIbeZRFkUGsWTFlvz2OoaBLoNtv5gg== + +xterm@3.15.0-beta67: + version "3.15.0-beta67" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.15.0-beta67.tgz#71973e174bdc08df620945eecd3f87912f1ac550" + integrity sha512-qLfo9GHVlu/IxgDI3vRGObWZM7UL4eLhMfjZhprx2aXNMpzmrOW6l3JDRsCjUWm93EoVavbULtnDhGSiTlKitQ== diff --git a/remote/yarn.lock b/remote/yarn.lock new file mode 100644 index 00000000000..019b237911f --- /dev/null +++ b/remote/yarn.lock @@ -0,0 +1,1185 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +agent-base@4, agent-base@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce" + integrity sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg== + dependencies: + es6-promisify "^5.0.0" + +agent-base@~4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" + integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== + dependencies: + es6-promisify "^5.0.0" + +applicationinsights@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" + integrity sha512-KzOOGdphOS/lXWMFZe5440LUdFbrLpMvh2SaRxn7BmiI550KAoSb2gIhiq6kJZ9Ir3AxRRztjhzif+e5P5IXIg== + dependencies: + diagnostic-channel "0.2.0" + diagnostic-channel-publishers "0.2.1" + zone.js "0.7.6" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +binary-extensions@^1.0.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.10.0.tgz#9aeb9a6c5e88638aad171e167f5900abe24835d0" + integrity sha1-muuabF6IY4qtFx4Wf1kAq+JINdA= + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +debug@3.1.0, debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +diagnostic-channel-publishers@0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" + integrity sha1-ji1geottef6IC1SLxYzGvrKIxPM= + +diagnostic-channel@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17" + integrity sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc= + dependencies: + semver "^5.3.0" + +eachr@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/eachr/-/eachr-3.2.0.tgz#2c35e43ea086516f7997cf80b7aa64d55a4a4484" + integrity sha1-LDXkPqCGUW95l8+At6pk1VpKRIQ= + dependencies: + editions "^1.1.1" + typechecker "^4.3.0" + +editions@^1.1.1, editions@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" + integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== + +editions@^2.1.0, editions@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/editions/-/editions-2.1.3.tgz#727ccf3ec2c7b12dcc652c71000f16c4824d6f7d" + integrity sha512-xDZyVm0A4nLgMNWVVLJvcwMjI80ShiH/27RyLiCnW1L273TcJIA25C4pwJ33AWV01OX6UriP35Xu+lH4S7HWQw== + dependencies: + errlop "^1.1.1" + semver "^5.6.0" + +errlop@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/errlop/-/errlop-1.1.1.tgz#d9ae4c76c3e64956c5d79e6e035d6343bfd62250" + integrity sha512-WX7QjiPHhsny7/PQvrhS5VMizXXKoKCS3udaBp8gjlARdbn+XmK300eKBAAN0hGyRaTCtRpOaxK+xFVPUJ3zkw== + dependencies: + editions "^2.1.2" + +es6-promise@^4.0.3: + version "4.2.4" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" + integrity sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extract-opts@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-3.3.1.tgz#5abbedc98c0d5202e3278727f9192d7e086c6be1" + integrity sha1-WrvtyYwNUgLjJ4cn+Rktfghsa+E= + dependencies: + eachr "^3.2.0" + editions "^1.1.1" + typechecker "^4.3.0" + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fs-extra@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getmac@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/getmac/-/getmac-1.4.1.tgz#cfefcb3ee7d7a73cba5292129cb100c19afbe17a" + integrity sha512-mQp+8D+grQX0gG8EJn6VfH0PxE56ZKNsTguOMxPShAiVk9lvH8Ey36eXepG705Ac1HCsvaSrQ/6bPHZ0++F/Mg== + dependencies: + editions "^1.3.4" + extract-opts "^3.2.0" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +graceful-fs@4.1.11, graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= + +graceful-fs@^4.1.11, graceful-fs@^4.1.6: + version "4.2.0" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" + integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +http-proxy-agent@2.1.0, http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" + integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== + dependencies: + agent-base "4" + debug "3.1.0" + +https-proxy-agent@2.2.1, https-proxy-agent@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" + integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ== + dependencies: + agent-base "^4.1.0" + debug "^3.1.0" + +iconv-lite@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.0.tgz#59cdde0a2a297cc2aeb0c6445a195ee89f127550" + integrity sha512-NnEhI9hIEKHOzJ4f697DMz9IQEXr/MMJ5w64vN2/4Ai+wRnvV7SBrL0KLoRlwaKVghOc7LQ5YkPLuX146b6Ydw== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ip@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.0.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b" + integrity sha1-z8hszV3FpS+oBIkRHGkgxFfi2Ys= + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +jschardet@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.6.0.tgz#c7d1a71edcff2839db2f9ec30fc5d5ebd3c1a678" + integrity sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +kind-of@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.0.4.tgz#7b8ecf18a4e17f8269d73b501c9f232c96887a74" + integrity sha1-e47PGKThf4Jp1ztQHJ8jLJaIenQ= + dependencies: + is-buffer "^1.0.2" + +kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + +lodash.isundefined@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz#23ef3d9535565203a66cefd5b830f848911afb48" + integrity sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g= + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +micromatch@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +nan@^2.0.0, nan@^2.12.1, nan@^2.13.2, nan@^2.14.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +native-watchdog@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/native-watchdog/-/native-watchdog-1.0.0.tgz#97344e83cd6815a8c8e6c44a52e7be05832e65ca" + integrity sha512-HKQATz5KLUMPyQQ/QaalzgTXaGz2plYPBxjyalaR4ECIu/UznXY8YJD+a9SLkkcvtxnJ8/zHLY3xik06vUZ7uA== + +node-addon-api@1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.2.tgz#d8aad9781a5cfc4132cc2fecdbdd982534265217" + integrity sha512-479Bjw9nTE5DdBSZZWprFryHGjUaQC31y1wHo19We/k0BZlrmhqQitWoUL0cD8+scljCbIUL+E58oRDEakdGGA== + +node-pty@0.9.0-beta19: + version "0.9.0-beta19" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.9.0-beta19.tgz#0fd381b2006f4665c4c2ee0509219e591842371a" + integrity sha512-MkKEvBnauGnzgXNr/oaoWQLVXm1gheIKZs4YQp8883ZiETmbEnpSvD0FU3bELcPXG5VFPRqIGsQJ4KUMBLzkPA== + dependencies: + nan "^2.13.2" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +nsfw@1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/nsfw/-/nsfw-1.2.5.tgz#febe581af616f7b042f89df133abe62416c4c803" + integrity sha512-m3mwZUKXiCR69PDMLfAmKmiNzy0Oe9LhFE0DYZC5cc1htNj5Hyb1sAgglXhuaDkibFy22AVvPC5cCFB3A6mYIw== + dependencies: + fs-extra "^7.0.0" + lodash.isinteger "^4.0.4" + lodash.isundefined "^3.0.1" + nan "^2.0.0" + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +onigasm-umd@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/onigasm-umd/-/onigasm-umd-2.2.2.tgz#b989d762df61f899a3052ac794a50bd93fe20257" + integrity sha512-v2eMOJu7iE444L2iJN+U6s6s5S0y7oj/N0DAkrd6wokRtTVoq/v/yaDI1lIqFrTeJbNtqNzYvguDF5yNzW3Rvw== + +oniguruma@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/oniguruma/-/oniguruma-7.2.0.tgz#c9a59c1ea7b9fe67e237a02e02139b638856f3af" + integrity sha512-bh+ZLdykY1sdIx8jBp2zpLbVFDBc3XmKH4Ceo2lijNaN1WhEqtnpqFlmtCbRuDB17nJ58RAUStVwfW8e8uEbnA== + dependencies: + nan "^2.14.0" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +picomatch@^2.0.4: + version "2.0.7" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" + integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= + +readable-stream@^2.0.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + integrity sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" + util-deprecate "~1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo= + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver-umd@^5.5.3: + version "5.5.3" + resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.3.tgz#b64d7a2d4f5a717b369d56e31940a38e47e34d1e" + integrity sha512-HOnQrn2iKnVe/xlqCTzMXQdvSz3rPbD0DmQXYuQ+oK1dpptGFfPghonQrx5JHl2O7EJwDqtQnjhE7ME23q6ngw== + +semver@^5.3.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== + +semver@^5.6.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +smart-buffer@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.1.tgz#07ea1ca8d4db24eb4cac86537d7d18995221ace3" + integrity sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg== + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +socks-proxy-agent@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz#5936bf8b707a993079c6f37db2091821bffa6473" + integrity sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw== + dependencies: + agent-base "~4.2.0" + socks "~2.2.0" + +socks@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.1.tgz#68ad678b3642fbc5d99c64c165bc561eab0215f9" + integrity sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w== + dependencies: + ip "^1.1.5" + smart-buffer "^4.0.1" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +spdlog@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/spdlog/-/spdlog-0.9.0.tgz#c85dd9d0b9cd385f6f3f5b92dc9d2e1691092b5c" + integrity sha512-AeLWPCYjGi4w5DfpXFKb9pCdgMe4gFBMroGfgwXiNfzwmcNYGoFQkIuD1MChZBR1Iwrx0nGhsTSHFslt/qfTAQ== + dependencies: + bindings "^1.5.0" + mkdirp "^0.5.1" + nan "^2.14.0" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +string_decoder@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ== + dependencies: + safe-buffer "~5.1.0" + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +typechecker@^4.3.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.7.0.tgz#5249f427358f45b7250c4924fd4d01ed9ba435e9" + integrity sha512-4LHc1KMNJ6NDGO+dSM/yNfZQRtp8NN7psYrPHUblD62Dvkwsp3VShsbM78kOgpcmMkRTgvwdKOTjctS+uMllgQ== + dependencies: + editions "^2.1.0" + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" + integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +vscode-anymatch@3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vscode-anymatch/-/vscode-anymatch-3.0.3.tgz#5a79101e6df7e659a1f070367bc42f190eb4ae76" + integrity sha512-qQgfbzJJ5nNShh4jjC3BBekY4d8emcxHFgnqcXwsB/PUKvJPCg7AZYXM7hqS7EDnKrX9tsIFwFMihZ7yut92Qg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +vscode-chokidar@2.1.7: + version "2.1.7" + resolved "https://registry.yarnpkg.com/vscode-chokidar/-/vscode-chokidar-2.1.7.tgz#c5b31eb87402f4779bb4170915245bdcb6f7854b" + integrity sha512-uSNEQetPjAlgIAHmcF9E6M+KCw0f842rsEnJ64aamUAV6TO7gkXNCvLSzb4MuLsPU7ZQyCa++DrLQFjvciK5dg== + dependencies: + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + vscode-anymatch "3.0.3" + optionalDependencies: + vscode-fsevents "1.2.12" + +vscode-fsevents@1.2.12: + version "1.2.12" + resolved "https://registry.yarnpkg.com/vscode-fsevents/-/vscode-fsevents-1.2.12.tgz#01a71a01f90ee95ca822c34427aba437a17c03a7" + integrity sha512-bH/jRdDpSesGpqiVLjp6gHLSKUOh7oNvppzZ17JIrdbRYCcDmV7dIWR5gQc27DFy0RD9JDT+t+ixMid94MkM1A== + dependencies: + nan "^2.14.0" + +vscode-proxy-agent@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/vscode-proxy-agent/-/vscode-proxy-agent-0.4.0.tgz#574833e65405c6333f350f1b9fef9909deccb6b5" + integrity sha512-L+WKjDOXRPxpq31Uj1Wr3++jaNNmhykn8JnGoYcwepbTnUwJKCbyyXRgb/hlBx0LXsF+k3BsnXt+r+5Q8rm97g== + dependencies: + debug "3.1.0" + http-proxy-agent "2.1.0" + https-proxy-agent "2.2.1" + socks-proxy-agent "4.0.1" + +vscode-ripgrep@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.5.5.tgz#24c0e9cb356cf889c98e15ecb58f9cf654a1d961" + integrity sha512-OrPrAmcun4+uZAuNcQvE6CCPskh+5AsjANod/Q3zRcJcGNxgoOSGlQN9RPtatkUNmkN8Nn8mZBnS1jMylu/dKg== + +vscode-textmate@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.2.2.tgz#0b4dabc69a6fba79a065cb6b615f66eac07c8f4c" + integrity sha512-1U4ih0E/KP1zNK/EbpUqyYtI7PY+Ccd2nDGTtiMR/UalLFnmaYkwoWhN1oI7B91ptBN8NdVwWuvyUnvJAulCUw== + dependencies: + oniguruma "^7.2.0" + +vscode-windows-ca-certs@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/vscode-windows-ca-certs/-/vscode-windows-ca-certs-0.1.0.tgz#d58eeb40b536130918cfde2b01e6dc7e5c1bd757" + integrity sha512-ZfZbfJIE09Q0dwGqmqTj7kuAq4g6lul9WPJvo0DkKjln8/FL+dY3wUKIKbYwWQp4x56SBTLBq3tJkD72xQ9Gqw== + dependencies: + node-addon-api "1.6.2" + +vscode-windows-registry@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vscode-windows-registry/-/vscode-windows-registry-1.0.1.tgz#bc9f765563eb6dc1c9ad9a41f9eaacc84dfadc7c" + integrity sha512-q0aKXi9Py1OBdmXIJJFeJBzpPJMMUxMJNBU9FysWIXEwJyMQGEVevKzM2J3Qz/cHSc5LVqibmoUWzZ7g+97qRg== + dependencies: + nan "^2.12.1" + +xterm-addon-search@0.2.0-beta3: + version "0.2.0-beta3" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.2.0-beta3.tgz#710ce14658e269c5a4791f5a9e2f520883a2e62b" + integrity sha512-KzVdkEtGbKJe9ER2TmrI7XjF/wUq1lir9U63vPJi0t2ymQvIECl1V63f9QtOp1vvpdhbZiXBxO+vGTj+y0tRow== + +xterm-addon-web-links@0.1.0-beta10: + version "0.1.0-beta10" + resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.1.0-beta10.tgz#610fa9773a2a5ccd41c1c83ba0e2dd2c9eb66a23" + integrity sha512-xfpjy0V6bB4BR44qIgZQPoCMVakxb65gMscPkHpO//QxvUxKzabV3dxOsIbeZRFkUGsWTFlvz2OoaBLoNtv5gg== + +xterm@3.15.0-beta90: + version "3.15.0-beta90" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.15.0-beta90.tgz#e1732c2914584c86cffa797ba762c482f21ce182" + integrity sha512-eixIA5brfoez+Y8bJPCcIw8Q7LgOvxRX3cPBaGmo7ozUASx9IEGOmvIRQX1ozTUmxEiXPnAxOfl/isQ+yNlaww== + +yauzl@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + +yazl@^2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.4.3.tgz#ec26e5cc87d5601b9df8432dbdd3cd2e5173a071" + integrity sha1-7CblzIfVYBud+EMtvdPNLlFzoHE= + dependencies: + buffer-crc32 "~0.2.3" + +zone.js@0.7.6: + version "0.7.6" + resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" + integrity sha1-+7w50+AmHQmG8boGMG6zrrDSIAk= diff --git a/resources/completions/bash/code b/resources/completions/bash/code index e377c5d24e2..f40963db05c 100644 --- a/resources/completions/bash/code +++ b/resources/completions/bash/code @@ -50,7 +50,7 @@ _code() --uninstall-extension --enable-proposed-api --verbose --log -s --status -p --performance --prof-startup --disable-extensions --disable-extension --inspect-extensions - --inspect-brk-extensions --disable-gpu --upload-logs + --inspect-brk-extensions --disable-gpu --max-memory=' -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace return diff --git a/resources/completions/zsh/_code b/resources/completions/zsh/_code index 9579cffb2f6..265c199f62f 100644 --- a/resources/completions/zsh/_code +++ b/resources/completions/zsh/_code @@ -14,8 +14,10 @@ arguments=( '--user-data-dir[specify the directory that user data is kept in]:directory:_directories' '(- *)'{-v,--version}'[print version]' '(- *)'{-h,--help}'[print usage]' + '(- *)'{--telemetry}'[Shows all telemetry events which VS code collects.]' '--extensions-dir[set the root path for extensions]:root path:_directories' '--list-extensions[list the installed extensions]' + '--category[filters instaled extension list by category, when using --list-extension]' '--show-versions[show versions of installed extensions, when using --list-extension]' '--install-extension[install an extension]:id or path:_files -g "*.vsix(-.)"' '--uninstall-extension[uninstall an extension]:id or path:_files -g "*.vsix(-.)"' @@ -30,7 +32,6 @@ arguments=( '--inspect-extensions[allow debugging and profiling of extensions]' '--inspect-brk-extensions[allow debugging and profiling of extensions with the extension host being paused after start]' '--disable-gpu[disable GPU hardware acceleration]' - '--upload-logs[upload logs from current session to a secure endpoint]:confirm:(iConfirmLogsUpload)' '--max-memory=[max memory size for a window (in Mbytes)]:size (Mbytes)' '*:file or directory:_files' ) diff --git a/resources/linux/bin/code.sh b/resources/linux/bin/code.sh index 55f50b6f1c1..64109f1fa12 100755 --- a/resources/linux/bin/code.sh +++ b/resources/linux/bin/code.sh @@ -3,6 +3,15 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. +# test that VSCode wasn't installed inside WSL +if grep -qi Microsoft /proc/version; then + echo "To use VS Code with the Windows Subsystem for Linux, please install VS Code in Windows and uninstall the Linux version in WSL. You can then use the '@@PRODNAME@@' command in a WSL terminal just as you would in a normal command prompt." 1>&2 + read -e -p "Do you want to continue anyways ? [y/N] " YN + + [[ $YN == "n" || $YN == "N" || $YN == "" ]] && exit 1 +fi + + # If root, ensure that --user-data-dir or --file-write is specified if [ "$(id -u)" = "0" ]; then for i in $@ diff --git a/resources/linux/code.desktop b/resources/linux/code.desktop index f93060d565b..dbc7818cecf 100644 --- a/resources/linux/code.desktop +++ b/resources/linux/code.desktop @@ -5,7 +5,7 @@ GenericName=Text Editor Exec=/usr/share/@@NAME@@/@@NAME@@ --unity-launch %F Icon=@@ICON@@ Type=Application -StartupNotify=true +StartupNotify=false StartupWMClass=@@NAME_SHORT@@ Categories=Utility;TextEditor;Development;IDE; MimeType=text/plain;inode/directory; diff --git a/resources/linux/rpm/code.spec.template b/resources/linux/rpm/code.spec.template index c3ce219f28f..c942d65a745 100644 --- a/resources/linux/rpm/code.spec.template +++ b/resources/linux/rpm/code.spec.template @@ -18,14 +18,14 @@ Visual Studio Code is a new choice of tool that combines the simplicity of a cod mkdir -p %{buildroot}/usr/share/@@NAME@@ mkdir -p %{buildroot}/usr/share/applications mkdir -p %{buildroot}/usr/share/pixmaps -mkdir -p %{buildroot}/usr/share/bash-completion/completions -mkdir -p %{buildroot}/usr/share/zsh/site-functions +#mkdir -p %{buildroot}/usr/share/bash-completion/completions +#mkdir -p %{buildroot}/usr/share/zsh/site-functions cp -r usr/share/@@NAME@@/* %{buildroot}/usr/share/@@NAME@@ cp -r usr/share/applications/@@NAME@@.desktop %{buildroot}/usr/share/applications cp -r usr/share/applications/@@NAME@@-url-handler.desktop %{buildroot}/usr/share/applications -cp -r usr/share/pixmaps/@@NAME@@.png %{buildroot}/usr/share/pixmaps -cp usr/share/bash-completion/completions/code %{buildroot}/usr/share/bash-completion/completions/code -cp usr/share/zsh/site-functions/_code %{buildroot}/usr/share/zsh/site-functions/_code +cp -r usr/share/pixmaps/@@ICON@@.png %{buildroot}/usr/share/pixmaps +#cp usr/share/bash-completion/completions/code %{buildroot}/usr/share/bash-completion/completions/code +#cp usr/share/zsh/site-functions/_code %{buildroot}/usr/share/zsh/site-functions/_code %post # Remove the legacy bin command if this is the stable build @@ -57,6 +57,6 @@ fi /usr/share/@@NAME@@/ /usr/share/applications/@@NAME@@.desktop /usr/share/applications/@@NAME@@-url-handler.desktop -/usr/share/pixmaps/@@NAME@@.png -/usr/share/bash-completion/completions/code -/usr/share/zsh/site-functions/_code +/usr/share/pixmaps/@@ICON@@.png +#/usr/share/bash-completion/completions/code +#/usr/share/zsh/site-functions/_code diff --git a/resources/linux/rpm/dependencies.json b/resources/linux/rpm/dependencies.json index d0b64c4fa68..34f127e1ae5 100644 --- a/resources/linux/rpm/dependencies.json +++ b/resources/linux/rpm/dependencies.json @@ -63,83 +63,5 @@ "libxcb.so.1()(64bit)", "libxkbfile.so.1()(64bit)", "libsecret-1.so.0()(64bit)" - ], - "i386": [ - "ld-linux.so.2", - "ld-linux.so.2(GLIBC_2.1)", - "libX11-xcb.so.1", - "libX11.so.6", - "libXcomposite.so.1", - "libXcursor.so.1", - "libXdamage.so.1", - "libXext.so.6", - "libXfixes.so.3", - "libXi.so.6", - "libXrandr.so.2", - "libXrender.so.1", - "libXss.so.1", - "libXtst.so.6", - "libasound.so.2", - "libatk-1.0.so.0", - "libc.so.6", - "libc.so.6(GLIBC_2.0)", - "libc.so.6(GLIBC_2.1)", - "libc.so.6(GLIBC_2.1.3)", - "libc.so.6(GLIBC_2.11)", - "libc.so.6(GLIBC_2.2)", - "libc.so.6(GLIBC_2.2.3)", - "libc.so.6(GLIBC_2.3)", - "libc.so.6(GLIBC_2.3.2)", - "libc.so.6(GLIBC_2.3.4)", - "libc.so.6(GLIBC_2.4)", - "libc.so.6(GLIBC_2.6)", - "libc.so.6(GLIBC_2.7)", - "libcairo.so.2", - "libcups.so.2", - "libdbus-1.so.3", - "libdl.so.2", - "libdl.so.2(GLIBC_2.0)", - "libdl.so.2(GLIBC_2.1)", - "libexpat.so.1", - "libfontconfig.so.1", - "libfreetype.so.6", - "libgcc_s.so.1", - "libgcc_s.so.1(GCC_4.0.0)", - "libgcc_s.so.1(GLIBC_2.0)", - "libgdk-x11-2.0.so.0", - "libgdk_pixbuf-2.0.so.0", - "libgio-2.0.so.0", - "libglib-2.0.so.0", - "libgmodule-2.0.so.0", - "libgobject-2.0.so.0", - "libgtk-3.so.0", - "libm.so.6", - "libm.so.6(GLIBC_2.0)", - "libm.so.6(GLIBC_2.1)", - "libnspr4.so", - "libnss3.so", - "libnssutil3.so", - "libpango-1.0.so.0", - "libpangocairo-1.0.so.0", - "libpthread.so.0", - "libpthread.so.0(GLIBC_2.0)", - "libpthread.so.0(GLIBC_2.1)", - "libpthread.so.0(GLIBC_2.2)", - "libpthread.so.0(GLIBC_2.2.3)", - "libpthread.so.0(GLIBC_2.3.2)", - "libpthread.so.0(GLIBC_2.3.3)", - "librt.so.1", - "librt.so.1(GLIBC_2.2)", - "libsmime3.so", - "libstdc++.so.6", - "libstdc++.so.6(GLIBCXX_3.4)", - "libstdc++.so.6(GLIBCXX_3.4.10)", - "libstdc++.so.6(GLIBCXX_3.4.11)", - "libstdc++.so.6(GLIBCXX_3.4.14)", - "libstdc++.so.6(GLIBCXX_3.4.15)", - "libstdc++.so.6(GLIBCXX_3.4.9)", - "libxcb.so.1", - "libxkbfile.so.1", - "libsecret-1.so.0" ] } \ No newline at end of file diff --git a/resources/linux/snap/electron-launch b/resources/linux/snap/electron-launch index 6fdd68a34cf..2a1c4395187 100755 --- a/resources/linux/snap/electron-launch +++ b/resources/linux/snap/electron-launch @@ -1,6 +1,34 @@ -#!/bin/sh +#!/usr/bin/env bash -# Create $XDG_RUNTIME_DIR if it doesn't exist +# On Fedora $SNAP is under /var and there is some magic to map it to /snap. +# We need to handle that case and reset $SNAP +SNAP=$(echo $SNAP | sed -e "s|/var/lib/snapd||g") + +if [ "$SNAP_ARCH" == "amd64" ]; then + ARCH="x86_64-linux-gnu" +elif [ "$SNAP_ARCH" == "armhf" ]; then + ARCH="arm-linux-gnueabihf" +elif [ "$SNAP_ARCH" == "arm64" ]; then + ARCH="aarch64-linux-gnu" +else + ARCH="$SNAP_ARCH-linux-gnu" +fi + +export XDG_CACHE_HOME=$SNAP_USER_COMMON/.cache +if [[ -d $SNAP_USER_DATA/.cache && ! -e $XDG_CACHE_HOME ]]; then + # the .cache directory used to be stored under $SNAP_USER_DATA, migrate it + mv $SNAP_USER_DATA/.cache $SNAP_USER_COMMON/ +fi +mkdir -p $XDG_CACHE_HOME + +# Gdk-pixbuf loaders +export GDK_PIXBUF_MODULE_FILE=$XDG_CACHE_HOME/gdk-pixbuf-loaders.cache +export GDK_PIXBUF_MODULEDIR=$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/2.10.0/loaders +if [ -f $SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders ]; then + $SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders > $GDK_PIXBUF_MODULE_FILE +fi + +# Create $XDG_RUNTIME_DIR if not exists (to be removed when https://pad.lv/1656340 is fixed) [ -n "$XDG_RUNTIME_DIR" ] && mkdir -p $XDG_RUNTIME_DIR -m 700 exec "$@" diff --git a/resources/linux/snap/snapUpdate.sh b/resources/linux/snap/snapUpdate.sh deleted file mode 100755 index 77569bfc16a..00000000000 --- a/resources/linux/snap/snapUpdate.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -sleep 2 -$SNAP_NAME \ No newline at end of file diff --git a/resources/linux/snap/snapcraft.yaml b/resources/linux/snap/snapcraft.yaml index e7971e8a7af..28b3e59ad7e 100644 --- a/resources/linux/snap/snapcraft.yaml +++ b/resources/linux/snap/snapcraft.yaml @@ -10,34 +10,55 @@ grade: stable confinement: classic parts: + gnome: + plugin: nil + build-packages: + - software-properties-common + override-pull: | + add-apt-repository -y ppa:ubuntu-desktop/gnome-3-26 + apt -y update + code: + after: + - gnome plugin: dump source: . stage-packages: + - fcitx-frontend-gtk3 + - gvfs-libs - libasound2 - - libc++1 + - libgconf-2-4 + - libglib2.0-bin + - libgnome-keyring0 + - libgtk-3-0 - libnotify4 - libnspr4 - libnss3 - libpcre3 - libpulse0 + - libsecret-1-0 - libxss1 - libxtst6 - - libxkbcommon0 - - libgtk-3-0 - - libgdk-pixbuf2.0-0 - - libglib2.0-bin - - unity-gtk2-module - - libappindicator1 - - xdg-user-dirs - - libsecret-1-0 - # TODO@joao @Tyriar check these deps - # - libatomic1 - # - libgtk2.0-bin + - zlib1g prime: - - -usr/share/dh-python + - -usr/share/doc + - -usr/share/fonts + - -usr/share/icons + - -usr/share/lintian + - -usr/share/man apps: @@NAME@@: - command: electron-launch ${SNAP}/usr/share/@@NAME@@/bin/@@NAME@@ - desktop: usr/share/applications/@@NAME@@.desktop \ No newline at end of file + command: electron-launch $SNAP/usr/share/@@NAME@@/bin/@@NAME@@ + desktop: usr/share/applications/@@NAME@@.desktop + common-id: @@NAME@@.desktop + environment: + DISABLE_WAYLAND: 1 + GSETTINGS_SCHEMA_DIR: $SNAP/usr/share/glib-2.0/schemas + + url-handler: + command: electron-launch $SNAP/usr/share/@@NAME@@/bin/@@NAME@@ --open-url + desktop: usr/share/applications/@@NAME@@-url-handler.desktop + environment: + DISABLE_WAYLAND: 1 + GSETTINGS_SCHEMA_DIR: $SNAP/usr/share/glib-2.0/schemas \ No newline at end of file diff --git a/resources/win32/bin/code.cmd b/resources/win32/bin/code.cmd index 4f31b474695..33c640f5dd1 100644 --- a/resources/win32/bin/code.cmd +++ b/resources/win32/bin/code.cmd @@ -2,5 +2,5 @@ setlocal set VSCODE_DEV= set ELECTRON_RUN_AS_NODE=1 -call "%~dp0..\@@NAME@@.exe" "%~dp0..\resources\app\out\cli.js" %* +"%~dp0..\@@NAME@@.exe" "%~dp0..\resources\app\out\cli.js" %* endlocal \ No newline at end of file diff --git a/resources/win32/bin/code.sh b/resources/win32/bin/code.sh index eaef0759a87..4bc4677e1e4 100644 --- a/resources/win32/bin/code.sh +++ b/resources/win32/bin/code.sh @@ -1,17 +1,42 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh # # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. - +COMMIT="@@COMMIT@@" +APP_NAME="@@APPNAME@@" +QUALITY="@@QUALITY@@" NAME="@@NAME@@" +DATAFOLDER="@@DATAFOLDER@@" VSCODE_PATH="$(dirname "$(dirname "$(realpath "$0")")")" ELECTRON="$VSCODE_PATH/$NAME.exe" -if grep -q Microsoft /proc/version; then - if [ -x /bin/wslpath ]; then - # On recent WSL builds, we just need to set WSLENV so that - # ELECTRON_RUN_AS_NODE is visible to the win32 process +if grep -qi Microsoft /proc/version; then + # in a wsl shell + if [ "$WSL_DISTRO_NAME" ]; then + # $WSL_DISTRO_NAME is available since WSL builds 18362, also for WSL2 + WSL_BUILD=18362 + else + WSL_BUILD=$(uname -r | sed -E 's/^.+-([0-9]+)-Microsoft/\1/') + if [ -z "$WSL_BUILD" ]; then + WSL_BUILD=0 + fi + fi + + if [ $WSL_BUILD -ge 17063 ]; then + # $WSL_DISTRO_NAME is available since WSL builds 18362, also for WSL2 + # WSLPATH is available since WSL build 17046 + # WSLENV is available since WSL build 17063 export WSLENV=ELECTRON_RUN_AS_NODE/w:$WSLENV CLI=$(wslpath -m "$VSCODE_PATH/resources/app/out/cli.js") + + # use the Remote WSL extension if installed + WSL_EXT_ID="ms-vscode-remote.remote-wsl" + WSL_EXT_WLOC=$(ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" --locate-extension $WSL_EXT_ID) + if [ -n "$WSL_EXT_WLOC" ]; then + # replace \r\n with \n in WSL_EXT_WLOC + WSL_CODE=$(wslpath -u "${WSL_EXT_WLOC%%[[:cntrl:]]}")/scripts/wslCode.sh + "$WSL_CODE" "$COMMIT" "$QUALITY" "$ELECTRON" "$APP_NAME" "$DATAFOLDER" "$@" + exit $? + fi else # If running under older WSL, don't pass cli.js to Electron as # environment vars cannot be transferred from WSL to Windows diff --git a/scripts/code-cli.bat b/scripts/code-cli.bat index 927e3e00d22..6fbf5edd626 100644 --- a/scripts/code-cli.bat +++ b/scripts/code-cli.bat @@ -17,7 +17,7 @@ set CODE=".build\electron\%NAMESHORT%" node build\lib\electron.js if %errorlevel% neq 0 node .\node_modules\gulp\bin\gulp.js electron -:: Manage build-in extensions +:: Manage built-in extensions if "%1"=="--builtin" goto builtin :: Sync built-in extensions diff --git a/scripts/code.sh b/scripts/code.sh index 8035059f65c..542efab5237 100755 --- a/scripts/code.sh +++ b/scripts/code.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -e + if [[ "$OSTYPE" == "darwin"* ]]; then realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; } ROOT=$(dirname "$(dirname "$(realpath "$0")")") @@ -9,6 +11,9 @@ if [[ "$OSTYPE" == "darwin"* ]]; then export ELECTRON_ENABLE_LOGGING=1 else ROOT=$(dirname "$(dirname "$(readlink -f $0)")") + if grep -qi Microsoft /proc/version; then + IN_WSL=true + fi fi function code() { @@ -50,4 +55,29 @@ function code() { exec "$CODE" . "$@" } +function code-wsl() +{ + # in a wsl shell + ELECTRON="$ROOT/.build/electron/Code - OSS.exe" + if [ -f "$ELECTRON" ]; then + local CWD=$(pwd) + cd $ROOT + export WSLENV=ELECTRON_RUN_AS_NODE/w:$WSLENV + local WSL_EXT_ID="ms-vscode-remote.remote-wsl" + local WSL_EXT_WLOC=$(ELECTRON_RUN_AS_NODE=1 "$ROOT/.build/electron/Code - OSS.exe" "out/cli.js" --locate-extension $WSL_EXT_ID) + cd $CWD + if [ -n "$WSL_EXT_WLOC" ]; then + # replace \r\n with \n in WSL_EXT_WLOC + local WSL_CODE=$(wslpath -u "${WSL_EXT_WLOC%%[[:cntrl:]]}")/scripts/wslCode-dev.sh + $WSL_CODE "$ROOT" "$@" + exit $? + else + echo "Remote WSL not installed, trying to run VSCode in WSL." + fi + fi +} + +if ! [ -z ${IN_WSL+x} ]; then + code-wsl "$@" +fi code "$@" diff --git a/scripts/env.ps1 b/scripts/env.ps1 deleted file mode 100644 index 72e094d0a6a..00000000000 --- a/scripts/env.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -$env:npm_config_disturl="https://atom.io/download/electron" -$env:npm_config_target=(node -p "require('./build/lib/electron').getElectronVersion();") -$env:npm_config_runtime="electron" diff --git a/scripts/env.sh b/scripts/env.sh deleted file mode 100755 index 8f641759b27..00000000000 --- a/scripts/env.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -export npm_config_disturl=https://atom.io/download/electron -export npm_config_target=$(node -p "require('./build/lib/electron').getElectronVersion();") -export npm_config_runtime=electron -export npm_config_cache="$HOME/.npm-electron" -mkdir -p "$npm_config_cache" diff --git a/scripts/generate-definitelytyped.sh b/scripts/generate-definitelytyped.sh new file mode 100755 index 00000000000..82de9124a07 --- /dev/null +++ b/scripts/generate-definitelytyped.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +if [ $# -eq 0 ]; then + echo "Pass in a version like ./scripts/generate-vscode-dts.sh 1.30." + echo "Failed to generate index.d.ts." + exit 1 +fi + +header="// Type definitions for Visual Studio Code ${1} +// Project: https://github.com/microsoft/vscode +// Definitions by: Visual Studio Code Team, Microsoft +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * See https://github.com/Microsoft/vscode/blob/master/LICENSE.txt for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Type Definition for Visual Studio Code ${1} Extension API + * See https://code.visualstudio.com/api for more information + */" + +if [ -f ./src/vs/vscode.d.ts ]; then + echo "$header" > index.d.ts + sed "1,4d" ./src/vs/vscode.d.ts >> index.d.ts + echo "Generated index.d.ts for version ${1}." +else + echo "Can't find ./src/vs/vscode.d.ts. Run this script at vscode root." +fi \ No newline at end of file diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index fc13a2d99b4..20567bc77cf 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -10,22 +10,26 @@ call .\scripts\test.bat --runGlob **\*.integrationTest.js %* if %errorlevel% neq 0 exit /b %errorlevel% :: Tests in the extension host -REM call .\scripts\code.bat %~dp0\..\extensions\vscode-api-tests\testWorkspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% -REM if %errorlevel% neq 0 exit /b %errorlevel% - -REM call .\scripts\code.bat %~dp0\..\extensions\vscode-api-tests\testworkspace.code-workspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% -REM if %errorlevel% neq 0 exit /b %errorlevel% - -call .\scripts\code.bat %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% +call .\scripts\code.bat %~dp0\..\extensions\vscode-api-tests\testWorkspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% if %errorlevel% neq 0 exit /b %errorlevel% -call .\scripts\code.bat $%~dp0\..\extensions\emmet\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% . +call .\scripts\code.bat %~dp0\..\extensions\vscode-api-tests\testworkspace.code-workspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% if %errorlevel% neq 0 exit /b %errorlevel% -# Tests in commonJS (HTML, CSS, JSON language server tests...) +call .\scripts\code.bat %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% +if %errorlevel% neq 0 exit /b %errorlevel% + +call .\scripts\code.bat $%~dp0\..\extensions\emmet\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disable-extensions --disable-inspect --user-data-dir=%VSCODEUSERDATADIR% . +if %errorlevel% neq 0 exit /b %errorlevel% + +:: Tests in commonJS (HTML, CSS, JSON language server tests...) call .\scripts\node-electron.bat .\node_modules\mocha\bin\_mocha .\extensions\*\server\out\test\**\*.test.js if %errorlevel% neq 0 exit /b %errorlevel% +if exist ".\resources\server\test\test-remote-integration.bat" ( + call .\resources\server\test\test-remote-integration.bat +) + rmdir /s /q %VSCODEUSERDATADIR% popd diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index a51f3ee172c..45595a5f0a3 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -16,14 +16,18 @@ cd $ROOT ./scripts/test.sh --runGlob **/*.integrationTest.js "$@" # Tests in the extension host -./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started -./scripts/code.sh $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started -./scripts/code.sh $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started -./scripts/code.sh $ROOT/extensions/markdown-language-features/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started +./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR +./scripts/code.sh $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR +./scripts/code.sh $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR +./scripts/code.sh $ROOT/extensions/markdown-language-features/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR -mkdir $ROOT/extensions/emmet/test-fixtures -./scripts/code.sh $ROOT/extensions/emmet/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started . -rm -r $ROOT/extensions/emmet/test-fixtures +mkdir -p $ROOT/extensions/emmet/test-fixtures +./scripts/code.sh $ROOT/extensions/emmet/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disable-extensions --skip-getting-started --disable-inspect --user-data-dir=$VSCODEUSERDATADIR +rm -rf $ROOT/extensions/emmet/test-fixtures + +if [ -f ./resources/server/test/test-remote-integration.sh ]; then + ./resources/server/test/test-remote-integration.sh +fi # Tests in commonJS cd $ROOT/extensions/css-language-features/server && $ROOT/scripts/node-electron.sh test/index.js diff --git a/src/bootstrap-fork.js b/src/bootstrap-fork.js index e30cadb0fca..c49274c99a7 100644 --- a/src/bootstrap-fork.js +++ b/src/bootstrap-fork.js @@ -11,6 +11,10 @@ const bootstrap = require('./bootstrap'); // Enable ASAR in our forked processes bootstrap.enableASARSupport(); +if (process.env['VSCODE_INJECT_NODE_MODULE_LOOKUP_PATH']) { + bootstrap.injectNodeModuleLookupPath(process.env['VSCODE_INJECT_NODE_MODULE_LOOKUP_PATH']); +} + // Configure: pipe logging to parent process if (!!process.send && process.env.PIPE_LOGGING === 'true') { pipeLoggingToParent(); diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index c41965b30ae..85548f51965 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -30,8 +30,24 @@ exports.load = function (modulePaths, resultCallback, options) { const path = require('path'); const args = parseURLQueryArgs(); + /** + * // configuration: IWindowConfiguration + * @type {{ + * zoomLevel?: number, + * extensionDevelopmentPath?: string | string[], + * extensionTestsPath?: string, + * userEnv?: { [key: string]: string | undefined }, + * appRoot?: string, + * nodeCachedDataDir?: string + * }} */ const configuration = JSON.parse(args['config'] || '{}') || {}; + // Apply zoom level early to avoid glitches + const zoomLevel = configuration.zoomLevel; + if (typeof zoomLevel === 'number' && zoomLevel !== 0) { + webFrame.setZoomLevel(zoomLevel); + } + // Error handler // @ts-ignore process.on('uncaughtException', function (error) { @@ -51,12 +67,6 @@ exports.load = function (modulePaths, resultCallback, options) { // Enable ASAR support bootstrap.enableASARSupport(path.join(configuration.appRoot, 'node_modules')); - // Apply zoom level early to avoid glitches - const zoomLevel = configuration.zoomLevel; - if (typeof zoomLevel === 'number' && zoomLevel !== 0) { - webFrame.setZoomLevel(zoomLevel); - } - if (options && typeof options.canModifyDOM === 'function') { options.canModifyDOM(configuration); } diff --git a/src/bootstrap.js b/src/bootstrap.js index 5f73a09dc7e..bb29caa6e82 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -20,6 +20,38 @@ process.on('SIGPIPE', () => { //#endregion +//#region Add support for redirecting the loading of node modules +exports.injectNodeModuleLookupPath = function (injectPath) { + if (!injectPath) { + throw new Error('Missing injectPath'); + } + + // @ts-ignore + const Module = require('module'); + const path = require('path'); + + const nodeModulesPath = path.join(__dirname, '../node_modules'); + + // @ts-ignore + const originalResolveLookupPaths = Module._resolveLookupPaths; + + // @ts-ignore + Module._resolveLookupPaths = function (moduleName, parent, newReturn) { + const result = originalResolveLookupPaths(moduleName, parent, newReturn); + + const paths = newReturn ? result : result[1]; + for (let i = 0, len = paths.length; i < len; i++) { + if (paths[i] === nodeModulesPath) { + paths.splice(i, 0, injectPath); + break; + } + } + + return result; + }; +}; +//#endregion + //#region Add support for using node_modules.asar /** * @param {string=} nodeModulesPath @@ -69,7 +101,15 @@ exports.uriFromPath = function (_path) { pathName = '/' + pathName; } - return encodeURI('file://' + pathName).replace(/#/g, '%23'); + /** @type {string} */ + let uri; + if (process.platform === 'win32' && pathName.startsWith('//')) { // specially handle Windows UNC paths + uri = encodeURI('file:' + pathName); + } else { + uri = encodeURI('file://' + pathName); + } + + return uri.replace(/#/g, '%23'); }; //#endregion @@ -110,6 +150,36 @@ exports.writeFile = function (file, content) { }); }); }; + +/** + * @param {string} dir + * @returns {Promise} + */ +function mkdir(dir) { + const fs = require('fs'); + + return new Promise((c, e) => fs.mkdir(dir, err => (err && err.code !== 'EEXIST') ? e(err) : c(dir))); +} + +/** + * @param {string} dir + * @returns {Promise} + */ +exports.mkdirp = function mkdirp(dir) { + const path = require('path'); + + return mkdir(dir).then(null, err => { + if (err && err.code === 'ENOENT') { + const parent = path.dirname(dir); + + if (parent !== dir) { // if not arrived at root + return mkdirp(parent).then(() => mkdir(dir)); + } + } + + throw err; + }); +}; //#endregion //#region NLS helpers diff --git a/src/buildfile.js b/src/buildfile.js index bd05c387ae0..0c77f1ae5fa 100644 --- a/src/buildfile.js +++ b/src/buildfile.js @@ -5,13 +5,23 @@ exports.base = [{ name: 'vs/base/common/worker/simpleWorker', - include: [ 'vs/editor/common/services/editorSimpleWorker' ], - prepend: [ 'vs/loader.js' ], - append: [ 'vs/base/worker/workerMain' ], + include: ['vs/editor/common/services/editorSimpleWorker'], + prepend: ['vs/loader.js'], + append: ['vs/base/worker/workerMain'], dest: 'vs/base/worker/workerMain.js' }]; -//@ts-ignore review + +exports.serviceWorker = [{ + name: 'vs/workbench/contrib/resources/browser/resourceServiceWorker', + // include: ['vs/editor/common/services/editorSimpleWorker'], + prepend: ['vs/loader.js'], + append: ['vs/workbench/contrib/resources/browser/resourceServiceWorkerMain'], + dest: 'vs/workbench/contrib/resources/browser/resourceServiceWorkerMain.js' +}]; + exports.workbench = require('./vs/workbench/buildfile').collectModules(['vs/workbench/workbench.main']); +exports.workbenchWeb = require('./vs/workbench/buildfile').collectModules(['vs/workbench/workbench.web.api']); + exports.code = require('./vs/code/buildfile').collectModules(); exports.entrypoint = function (name) { diff --git a/src/main.js b/src/main.js index 6b2bfae32c6..6902f1d6530 100644 --- a/src/main.js +++ b/src/main.js @@ -7,9 +7,10 @@ 'use strict'; const perf = require('./vs/base/common/performance'); +const lp = require('./vs/base/node/languagePacks'); + perf.mark('main:started'); -const fs = require('fs'); const path = require('path'); const bootstrap = require('./bootstrap'); const paths = require('./paths'); @@ -27,21 +28,6 @@ bootstrap.enableASARSupport(); // Set userData path before app 'ready' event and call to process.chdir const args = parseCLIArgs(); const userDataPath = getUserDataPath(args); - -// global storage migration needs to happen very early before app.on("ready") -// TODO@Ben remove after a while -try { - const globalStorageHome = path.join(userDataPath, 'User', 'globalStorage', 'state.vscdb'); - const localStorageHome = path.join(userDataPath, 'Local Storage'); - const localStorageDB = path.join(localStorageHome, 'file__0.localstorage'); - const localStorageDBBackup = path.join(localStorageHome, 'file__0.vscmig'); - if (!fs.existsSync(globalStorageHome) && fs.existsSync(localStorageDB)) { - fs.renameSync(localStorageDB, localStorageDBBackup); - } -} catch (error) { - console.error(error); -} - app.setPath('userData', userDataPath); // Update cwd based on environment and platform @@ -57,15 +43,19 @@ registerListeners(); */ let nlsConfiguration = undefined; const userDefinedLocale = getUserDefinedLocale(); -userDefinedLocale.then((locale) => { +const metaDataFile = path.join(__dirname, 'nls.metadata.json'); + +userDefinedLocale.then(locale => { if (locale && !nlsConfiguration) { - nlsConfiguration = getNLSConfiguration(locale); + nlsConfiguration = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale); } }); -// Configure command line switches +// Cached data const nodeCachedDataDir = getNodeCachedDir(); -configureCommandlineSwitches(args, nodeCachedDataDir); + +// Configure command line switches +configureCommandlineSwitches(args); // Load our code once ready app.once('ready', function () { @@ -89,7 +79,7 @@ function onReady() { Promise.all([nodeCachedDataDir.ensureExists(), userDefinedLocale]).then(([cachedDataDir, locale]) => { if (locale && !nlsConfiguration) { - nlsConfiguration = getNLSConfiguration(locale); + nlsConfiguration = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale); } if (!nlsConfiguration) { @@ -98,7 +88,7 @@ function onReady() { // First, we need to test a user defined locale. If it fails we try the app locale. // If that fails we fall back to English. - nlsConfiguration.then((nlsConfig) => { + nlsConfiguration.then(nlsConfig => { const startup = nlsConfig => { nlsConfig._languagePackSupport = true; @@ -106,7 +96,10 @@ function onReady() { process.env['VSCODE_NODE_CACHED_DATA_DIR'] = cachedDataDir || ''; // Load main in AMD - require('./bootstrap-amd').load('vs/code/electron-main/main'); + perf.mark('willLoadMainBundle'); + require('./bootstrap-amd').load('vs/code/electron-main/main', () => { + perf.mark('didLoadMainBundle'); + }); }; // We recevied a valid nlsConfig from a user defined locale @@ -126,7 +119,7 @@ function onReady() { // See above the comment about the loader and case sensitiviness appLocale = appLocale.toLowerCase(); - getNLSConfiguration(appLocale).then((nlsConfig) => { + lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, appLocale).then(nlsConfig => { if (!nlsConfig) { nlsConfig = { locale: appLocale, availableLanguages: {} }; } @@ -143,16 +136,14 @@ function onReady() { * @typedef {import('minimist').ParsedArgs} ParsedArgs * * @param {ParsedArgs} cliArgs - * @param {{ jsFlags: () => string }} nodeCachedDataDir */ -function configureCommandlineSwitches(cliArgs, nodeCachedDataDir) { +function configureCommandlineSwitches(cliArgs) { // Force pre-Chrome-60 color profile handling (for https://github.com/Microsoft/vscode/issues/51791) - // TODO@Ben check if future versions of Electron still support this flag - app.commandLine.appendSwitch('disable-features', 'ColorCorrectRendering'); + app.commandLine.appendSwitch('disable-color-correct-rendering'); // Support JS Flags - const jsFlags = resolveJSFlags(cliArgs, nodeCachedDataDir.jsFlags()); + const jsFlags = getJSFlags(cliArgs); if (jsFlags) { app.commandLine.appendSwitch('--js-flags', jsFlags); } @@ -160,10 +151,10 @@ function configureCommandlineSwitches(cliArgs, nodeCachedDataDir) { /** * @param {ParsedArgs} cliArgs - * @param {string[]} jsFlags * @returns {string} */ -function resolveJSFlags(cliArgs, ...jsFlags) { +function getJSFlags(cliArgs) { + const jsFlags = []; // Add any existing JS flags we already got from the command line if (cliArgs['js-flags']) { @@ -210,7 +201,7 @@ function parseCLIArgs() { function setCurrentWorkingDirectory() { try { if (process.platform === 'win32') { - process.env['VSCODE_CWD'] = process.cwd(); // remember as environment letiable + process.env['VSCODE_CWD'] = process.cwd(); // remember as environment variable process.chdir(path.dirname(app.getPath('exe'))); // always set application folder as cwd } else if (process.env['VSCODE_CWD']) { process.chdir(process.env['VSCODE_CWD']); @@ -258,7 +249,7 @@ function registerListeners() { } /** - * @returns {{ jsFlags: () => string; ensureExists: () => Promise, _compute: () => string; }} + * @returns {{ ensureExists: () => Promise }} */ function getNodeCachedDir() { return new class { @@ -267,12 +258,8 @@ function getNodeCachedDir() { this.value = this._compute(); } - jsFlags() { - return this.value ? '--nolazy' : undefined; - } - ensureExists() { - return mkdirp(this.value).then(() => this.value, () => { /*ignore*/ }); + return bootstrap.mkdirp(this.value).then(() => this.value, () => { /*ignore*/ }); } _compute() { @@ -302,7 +289,7 @@ function getNodeCachedDir() { * @returns {string} */ function stripComments(content) { - const regexp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g; + const regexp = /("(?:[^\\"]*(?:\\.)?)*")|('(?:[^\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g; return content.replace(regexp, function (match, m1, m2, m3, m4) { // Only one of m1, m2, m3, m4 matches @@ -325,101 +312,6 @@ function stripComments(content) { }); } -/** - * @param {string} dir - * @returns {Promise} - */ -function mkdir(dir) { - return new Promise((c, e) => fs.mkdir(dir, err => (err && err.code !== 'EEXIST') ? e(err) : c(dir))); -} - -/** - * @param {string} file - * @returns {Promise} - */ -function exists(file) { - return new Promise(c => fs.exists(file, c)); -} - -/** - * @param {string} file - * @returns {Promise} - */ -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} - */ -function lstat(file) { - return new Promise((c, e) => fs.lstat(file, (err, stats) => err ? e(err) : c(stats))); -} - -/** - * @param {string} dir - * @returns {Promise} - */ -function readdir(dir) { - return new Promise((c, e) => fs.readdir(dir, (err, files) => err ? e(err) : c(files))); -} - -/** - * @param {string} dir - * @returns {Promise} - */ -function rmdir(dir) { - return new Promise((c, e) => fs.rmdir(dir, err => err ? e(err) : c(undefined))); -} - -/** - * @param {string} file - * @returns {Promise} - */ -function unlink(file) { - return new Promise((c, e) => fs.unlink(file, err => err ? e(err) : c(undefined))); -} - -/** - * @param {string} dir - * @returns {Promise} - */ -function mkdirp(dir) { - return mkdir(dir).then(null, err => { - if (err && err.code === 'ENOENT') { - const parent = path.dirname(dir); - - if (parent !== dir) { // if not arrived at root - return mkdirp(parent).then(() => mkdir(dir)); - } - } - - throw err; - }); -} - -/** - * @param {string} location - * @returns {Promise} - */ -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; - }); -} - // Language tags are case insensitive however an amd loader is case sensitive // To make this work on case preserving & insensitive FS we do the following: // the language bundles have lower case language tags and we always lower case @@ -434,191 +326,16 @@ function getUserDefinedLocale() { } const localeConfig = path.join(userDataPath, 'User', 'locale.json'); - return exists(localeConfig).then((result) => { - if (result) { - return bootstrap.readFile(localeConfig).then((content) => { - content = stripComments(content); - try { - const value = JSON.parse(content).locale; - return value && typeof value === 'string' ? value.toLowerCase() : undefined; - } catch (e) { - return undefined; - } - }); - } else { + return bootstrap.readFile(localeConfig).then(content => { + content = stripComments(content); + try { + const value = JSON.parse(content).locale; + return value && typeof value === 'string' ? value.toLowerCase() : undefined; + } catch (e) { return undefined; } + }, () => { + return undefined; }); } - -/** - * @returns {object} - */ -function getLanguagePackConfigurations() { - const configFile = path.join(userDataPath, 'languagepacks.json'); - try { - return require(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 { - 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); - } - return undefined; -} - -/** - * @param {string} locale - */ -function getNLSConfiguration(locale) { - if (locale === 'pseudo') { - return Promise.resolve({ locale: locale, availableLanguages: {}, pseudo: true }); - } - - 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('nlsGeneration:start'); - - const defaultResult = function (locale) { - perf.mark('nlsGeneration:end'); - return Promise.resolve({ locale: locale, availableLanguages: {} }); - }; - try { - const commit = product.commit; - if (!commit) { - return defaultResult(initialLocale); - } - const configs = getLanguagePackConfigurations(); - 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); - } - 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('nlsGeneration:end'); - return result; - } - return mkdirp(coreLocation).then(() => { - return Promise.all([bootstrap.readFile(path.join(__dirname, 'nls.metadata.json')), bootstrap.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 (let bundle of bundles) { - const modules = metadata.bundles[bundle]; - const target = Object.create(null); - for (let 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(bootstrap.writeFile(path.join(coreLocation, bundle.replace(/\//g, '!') + '.nls.json'), JSON.stringify(target))); - } - writes.push(bootstrap.writeFile(translationsConfigFile, JSON.stringify(packConfig.translations))); - return Promise.all(writes); - }).then(() => { - perf.mark('nlsGeneration:end'); - 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); - } -} //#endregion diff --git a/src/tsconfig.base.json b/src/tsconfig.base.json index cebdfa90b3c..cfd4b390a62 100644 --- a/src/tsconfig.base.json +++ b/src/tsconfig.base.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "amd", "moduleResolution": "node", - "noImplicitAny": false, + "noImplicitAny": true, "target": "es5", "experimentalDecorators": true, "noImplicitReturns": true, @@ -10,6 +10,8 @@ "noImplicitThis": true, "alwaysStrict": true, "strictBindCallApply": true, + "strictNullChecks": true, + "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { "vs/*": [ diff --git a/src/tsconfig.json b/src/tsconfig.json index 4b9f4170455..7fbb44c3ec5 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -4,7 +4,14 @@ "removeComments": false, "preserveConstEnums": true, "sourceMap": false, - "outDir": "../out" + "outDir": "../out", + "target": "es6", + "lib": [ + "dom", + "es5", + "es2015.iterable", + "webworker" + ] }, "include": [ "./typings", @@ -13,4 +20,4 @@ "exclude": [ "./typings/require-monaco.d.ts" ] -} \ No newline at end of file +} diff --git a/src/tsconfig.monaco.json b/src/tsconfig.monaco.json index 1bf4732a4a0..32983503724 100644 --- a/src/tsconfig.monaco.json +++ b/src/tsconfig.monaco.json @@ -1,24 +1,23 @@ { + "extends": "./tsconfig.base.json", "compilerOptions": { "noEmit": true, + "types": [], + "paths": {}, "module": "amd", "moduleResolution": "classic", - "noImplicitAny": false, "removeComments": false, "preserveConstEnums": true, "target": "es5", "sourceMap": false, - "experimentalDecorators": true, - "declaration": true, - "noImplicitReturns": true, - "baseUrl": ".", - "types": [] + "declaration": true }, "include": [ "typings/require.d.ts", "./typings/require-monaco.d.ts", "typings/thenable.d.ts", "typings/es6-promise.d.ts", + "typings/lib.es2018.promise.d.ts", "typings/lib.array-ext.d.ts", "typings/lib.ie11_safe_es6.d.ts", "vs/css.d.ts", @@ -35,4 +34,4 @@ "exclude": [ "node_modules/*" ] -} \ No newline at end of file +} diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json deleted file mode 100644 index 4053664e995..00000000000 --- a/src/tsconfig.strictNullChecks.json +++ /dev/null @@ -1,849 +0,0 @@ -{ - "extends": "./tsconfig.base.json", - "compilerOptions": { - "noEmit": true, - "strictNullChecks": true - }, - "include": [ - "./typings", - "./vs/base/common/**/*.ts", - "./vs/base/node/**/*.ts", - "./vs/base/browser/**/*.ts", - "./vs/editor/common/**/*.ts", - "./vs/editor/browser/**/*.ts", - "./vs/editor/test/**/*.ts", - "./vs/editor/contrib/smartSelect/**/*.ts", - "./vs/editor/contrib/format/**/*.ts", - "./vs/editor/contrib/gotoError/**/*.ts", - "./vs/editor/contrib/inPlaceReplace/**/*.ts" - ], - "files": [ - "./vs/base/parts/contextmenu/common/contextmenu.ts", - "./vs/base/parts/contextmenu/electron-browser/contextmenu.ts", - "./vs/base/parts/contextmenu/electron-main/contextmenu.ts", - "./vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts", - "./vs/base/parts/ipc/electron-main/ipc.electron-main.ts", - "./vs/base/parts/ipc/node/ipc.cp.ts", - "./vs/base/parts/ipc/node/ipc.electron.ts", - "./vs/base/parts/ipc/node/ipc.net.ts", - "./vs/base/parts/ipc/node/ipc.ts", - "./vs/base/parts/ipc/test/node/ipc.cp.test.ts", - "./vs/base/parts/ipc/test/node/ipc.net.test.ts", - "./vs/base/parts/ipc/test/node/ipc.test.ts", - "./vs/base/parts/ipc/test/node/testApp.ts", - "./vs/base/parts/ipc/test/node/testService.ts", - "./vs/base/parts/quickopen/common/quickOpen.ts", - "./vs/base/parts/quickopen/common/quickOpenScorer.ts", - "./vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts", - "./vs/base/test/browser/browser.test.ts", - "./vs/base/test/browser/comparers.test.ts", - "./vs/base/test/browser/dom.test.ts", - "./vs/base/test/browser/highlightedLabel.test.ts", - "./vs/base/test/browser/htmlContent.test.ts", - "./vs/base/test/browser/progressBar.test.ts", - "./vs/base/test/browser/ui/contextview/contextview.test.ts", - "./vs/base/test/browser/ui/grid/grid.test.ts", - "./vs/base/test/browser/ui/grid/gridview.test.ts", - "./vs/base/test/browser/ui/grid/util.ts", - "./vs/base/test/browser/ui/list/listView.test.ts", - "./vs/base/test/browser/ui/list/rangeMap.test.ts", - "./vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts", - "./vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts", - "./vs/base/test/browser/ui/splitview/splitview.test.ts", - "./vs/base/test/browser/ui/tree/asyncDataTree.test.ts", - "./vs/base/test/browser/ui/tree/dataTree.test.ts", - "./vs/base/test/browser/ui/tree/indexTreeModel.test.ts", - "./vs/base/test/browser/ui/tree/objectTree.test.ts", - "./vs/base/test/browser/ui/tree/objectTreeModel.test.ts", - "./vs/base/test/common/arrays.test.ts", - "./vs/base/test/common/assert.test.ts", - "./vs/base/test/common/async.test.ts", - "./vs/base/test/common/cache.test.ts", - "./vs/base/test/common/cancellation.test.ts", - "./vs/base/test/common/charCode.test.ts", - "./vs/base/test/common/collections.test.ts", - "./vs/base/test/common/color.test.ts", - "./vs/base/test/common/decorators.test.ts", - "./vs/base/test/common/diff/diff.test.ts", - "./vs/base/test/common/errors.test.ts", - "./vs/base/test/common/event.test.ts", - "./vs/base/test/common/filters.perf.test.ts", - "./vs/base/test/common/filters.test.ts", - "./vs/base/test/common/hash.test.ts", - "./vs/base/test/common/history.test.ts", - "./vs/base/test/common/json.test.ts", - "./vs/base/test/common/jsonEdit.test.ts", - "./vs/base/test/common/jsonFormatter.test.ts", - "./vs/base/test/common/keyCodes.test.ts", - "./vs/base/test/common/labels.test.ts", - "./vs/base/test/common/lifecycle.test.ts", - "./vs/base/test/common/linkedList.test.ts", - "./vs/base/test/common/map.test.ts", - "./vs/base/test/common/marshalling.test.ts", - "./vs/base/test/common/mime.test.ts", - "./vs/base/test/common/objects.test.ts", - "./vs/base/test/common/octicon.test.ts", - "./vs/base/test/common/paging.test.ts", - "./vs/base/test/common/paths.test.ts", - "./vs/base/test/common/resources.test.ts", - "./vs/base/test/common/scrollable.test.ts", - "./vs/base/test/common/strings.test.ts", - "./vs/base/test/common/types.test.ts", - "./vs/base/test/common/uri.test.ts", - "./vs/base/test/common/utils.ts", - "./vs/base/test/common/uuid.test.ts", - "./vs/base/test/node/config.test.ts", - "./vs/base/test/node/console.test.ts", - "./vs/base/test/node/decoder.test.ts", - "./vs/base/test/node/encoding/encoding.test.ts", - "./vs/base/test/node/extfs/extfs.test.ts", - "./vs/base/test/node/flow.test.ts", - "./vs/base/test/node/glob.test.ts", - "./vs/base/test/node/id.test.ts", - "./vs/base/test/node/pfs.test.ts", - "./vs/base/test/node/port.test.ts", - "./vs/base/test/node/processes/fixtures/fork.ts", - "./vs/base/test/node/processes/fixtures/fork_large.ts", - "./vs/base/test/node/processes/processes.test.ts", - "./vs/base/test/node/storage/storage.test.ts", - "./vs/base/test/node/stream/stream.test.ts", - "./vs/base/test/node/uri.test.perf.ts", - "./vs/base/test/node/utils.ts", - "./vs/base/worker/defaultWorkerFactory.ts", - "./vs/base/worker/workerMain.ts", - "./vs/code/code.main.ts", - "./vs/code/electron-browser/issue/issueReporterMain.ts", - "./vs/code/electron-browser/issue/issueReporterModel.ts", - "./vs/code/electron-browser/issue/issueReporterPage.ts", - "./vs/code/electron-browser/issue/issueReporterUtil.ts", - "./vs/code/electron-browser/issue/test/testReporterModel.test.ts", - "./vs/code/electron-browser/processExplorer/processExplorerMain.ts", - "./vs/code/electron-browser/sharedProcess/contrib/contributions.ts", - "./vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner.ts", - "./vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner.ts", - "./vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner.ts", - "./vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts", - "./vs/code/electron-browser/sharedProcess/sharedProcessMain.ts", - "./vs/code/electron-main/auth.ts", - "./vs/code/electron-main/keyboard.ts", - "./vs/code/electron-main/logUploader.ts", - "./vs/code/electron-main/sharedProcess.ts", - "./vs/code/electron-main/theme.ts", - "./vs/code/node/cli.ts", - "./vs/code/node/cliProcessMain.ts", - "./vs/code/node/paths.ts", - "./vs/code/node/shellEnv.ts", - "./vs/code/node/wait.ts", - "./vs/code/node/windowsFinder.ts", - "./vs/code/test/node/argv.test.ts", - "./vs/code/test/node/windowsFinder.test.ts", - "./vs/editor/contrib/bracketMatching/bracketMatching.ts", - "./vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts", - "./vs/editor/contrib/caretOperations/caretOperations.ts", - "./vs/editor/contrib/caretOperations/moveCaretCommand.ts", - "./vs/editor/contrib/caretOperations/test/moveCarretCommand.test.ts", - "./vs/editor/contrib/caretOperations/transpose.ts", - "./vs/editor/contrib/clipboard/clipboard.ts", - "./vs/editor/contrib/codeAction/codeAction.ts", - "./vs/editor/contrib/codeAction/codeActionCommands.ts", - "./vs/editor/contrib/codeAction/codeActionContributions.ts", - "./vs/editor/contrib/codeAction/codeActionModel.ts", - "./vs/editor/contrib/codeAction/codeActionTrigger.ts", - "./vs/editor/contrib/codeAction/codeActionWidget.ts", - "./vs/editor/contrib/codeAction/lightBulbWidget.ts", - "./vs/editor/contrib/codeAction/test/codeAction.test.ts", - "./vs/editor/contrib/codeAction/test/codeActionModel.test.ts", - "./vs/editor/contrib/codelens/codelens.ts", - "./vs/editor/contrib/codelens/codelensController.ts", - "./vs/editor/contrib/codelens/codelensWidget.ts", - "./vs/editor/contrib/colorPicker/color.ts", - "./vs/editor/contrib/colorPicker/colorDetector.ts", - "./vs/editor/contrib/colorPicker/colorPickerModel.ts", - "./vs/editor/contrib/colorPicker/colorPickerWidget.ts", - "./vs/editor/contrib/comment/blockCommentCommand.ts", - "./vs/editor/contrib/comment/comment.ts", - "./vs/editor/contrib/comment/lineCommentCommand.ts", - "./vs/editor/contrib/comment/test/blockCommentCommand.test.ts", - "./vs/editor/contrib/comment/test/lineCommentCommand.test.ts", - "./vs/editor/contrib/contextmenu/contextmenu.ts", - "./vs/editor/contrib/cursorUndo/cursorUndo.ts", - "./vs/editor/contrib/dnd/dnd.ts", - "./vs/editor/contrib/dnd/dragAndDropCommand.ts", - "./vs/editor/contrib/find/findController.ts", - "./vs/editor/contrib/find/findDecorations.ts", - "./vs/editor/contrib/find/findModel.ts", - "./vs/editor/contrib/find/findOptionsWidget.ts", - "./vs/editor/contrib/find/findState.ts", - "./vs/editor/contrib/find/findWidget.ts", - "./vs/editor/contrib/find/replaceAllCommand.ts", - "./vs/editor/contrib/find/replacePattern.ts", - "./vs/editor/contrib/find/simpleFindWidget.ts", - "./vs/editor/contrib/find/test/find.test.ts", - "./vs/editor/contrib/find/test/findController.test.ts", - "./vs/editor/contrib/find/test/replacePattern.test.ts", - "./vs/editor/contrib/folding/folding.ts", - "./vs/editor/contrib/folding/foldingDecorations.ts", - "./vs/editor/contrib/folding/foldingModel.ts", - "./vs/editor/contrib/folding/foldingRanges.ts", - "./vs/editor/contrib/folding/hiddenRangeModel.ts", - "./vs/editor/contrib/folding/indentRangeProvider.ts", - "./vs/editor/contrib/folding/intializingRangeProvider.ts", - "./vs/editor/contrib/folding/syntaxRangeProvider.ts", - "./vs/editor/contrib/folding/test/foldingModel.test.ts", - "./vs/editor/contrib/folding/test/foldingRanges.test.ts", - "./vs/editor/contrib/folding/test/hiddenRangeModel.test.ts", - "./vs/editor/contrib/folding/test/indentFold.test.ts", - "./vs/editor/contrib/folding/test/indentRangeProvider.test.ts", - "./vs/editor/contrib/folding/test/syntaxFold.test.ts", - "./vs/editor/contrib/fontZoom/fontZoom.ts", - "./vs/editor/contrib/goToDefinition/clickLinkGesture.ts", - "./vs/editor/contrib/goToDefinition/goToDefinition.ts", - "./vs/editor/contrib/hover/getHover.ts", - "./vs/editor/contrib/hover/hover.ts", - "./vs/editor/contrib/hover/hoverOperation.ts", - "./vs/editor/contrib/hover/hoverWidgets.ts", - "./vs/editor/contrib/hover/modesContentHover.ts", - "./vs/editor/contrib/hover/modesGlyphHover.ts", - "./vs/editor/contrib/indentation/indentUtils.ts", - "./vs/editor/contrib/indentation/indentation.ts", - "./vs/editor/contrib/indentation/test/indentation.test.ts", - "./vs/editor/contrib/linesOperations/copyLinesCommand.ts", - "./vs/editor/contrib/linesOperations/deleteLinesCommand.ts", - "./vs/editor/contrib/linesOperations/linesOperations.ts", - "./vs/editor/contrib/linesOperations/moveLinesCommand.ts", - "./vs/editor/contrib/linesOperations/sortLinesCommand.ts", - "./vs/editor/contrib/linesOperations/test/copyLinesCommand.test.ts", - "./vs/editor/contrib/linesOperations/test/deleteLinesCommand.test.ts", - "./vs/editor/contrib/linesOperations/test/linesOperations.test.ts", - "./vs/editor/contrib/linesOperations/test/moveLinesCommand.test.ts", - "./vs/editor/contrib/linesOperations/test/sortLinesCommand.test.ts", - "./vs/editor/contrib/links/getLinks.ts", - "./vs/editor/contrib/links/links.ts", - "./vs/editor/contrib/markdown/markdownRenderer.ts", - "./vs/editor/contrib/message/messageController.ts", - "./vs/editor/contrib/multicursor/multicursor.ts", - "./vs/editor/contrib/multicursor/test/multicursor.test.ts", - "./vs/editor/contrib/parameterHints/parameterHints.ts", - "./vs/editor/contrib/parameterHints/parameterHintsModel.ts", - "./vs/editor/contrib/parameterHints/parameterHintsWidget.ts", - "./vs/editor/contrib/parameterHints/provideSignatureHelp.ts", - "./vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts", - "./vs/editor/contrib/quickOpen/quickOpen.ts", - "./vs/editor/contrib/referenceSearch/peekViewWidget.ts", - "./vs/editor/contrib/referenceSearch/referencesModel.ts", - "./vs/editor/contrib/referenceSearch/referencesTree.ts", - "./vs/editor/contrib/referenceSearch/test/referencesModel.test.ts", - "./vs/editor/contrib/rename/rename.ts", - "./vs/editor/contrib/rename/renameInputField.ts", - "./vs/editor/contrib/snippet/snippetParser.ts", - "./vs/editor/contrib/snippet/snippetVariables.ts", - "./vs/editor/contrib/snippet/test/snippetParser.test.ts", - "./vs/editor/contrib/snippet/test/snippetVariables.test.ts", - "./vs/editor/contrib/suggest/completionModel.ts", - "./vs/editor/contrib/suggest/suggest.ts", - "./vs/editor/contrib/suggest/suggestAlternatives.ts", - "./vs/editor/contrib/suggest/suggestMemory.ts", - "./vs/editor/contrib/suggest/suggestWidget.ts", - "./vs/editor/contrib/suggest/test/completionModel.test.ts", - "./vs/editor/contrib/suggest/test/suggest.test.ts", - "./vs/editor/contrib/suggest/test/suggestMemory.test.ts", - "./vs/editor/contrib/suggest/wordContextKey.ts", - "./vs/editor/contrib/suggest/wordDistance.ts", - "./vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode.ts", - "./vs/editor/contrib/wordHighlighter/wordHighlighter.ts", - "./vs/editor/contrib/wordOperations/test/wordOperations.test.ts", - "./vs/editor/contrib/wordOperations/test/wordTestUtils.ts", - "./vs/editor/contrib/wordOperations/wordOperations.ts", - "./vs/editor/contrib/wordPartOperations/test/wordPartOperations.test.ts", - "./vs/editor/contrib/wordPartOperations/wordPartOperations.ts", - "./vs/editor/contrib/zoneWidget/zoneWidget.ts", - "./vs/editor/editor.worker.ts", - "./vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.ts", - "./vs/editor/standalone/browser/colorizer.ts", - "./vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.ts", - "./vs/editor/standalone/browser/inspectTokens/inspectTokens.ts", - "./vs/editor/standalone/browser/simpleServices.ts", - "./vs/editor/standalone/browser/standaloneCodeEditor.ts", - "./vs/editor/standalone/browser/standaloneCodeServiceImpl.ts", - "./vs/editor/standalone/browser/standaloneThemeServiceImpl.ts", - "./vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast.ts", - "./vs/editor/standalone/common/monarch/monarchCommon.ts", - "./vs/editor/standalone/common/monarch/monarchCompile.ts", - "./vs/editor/standalone/common/monarch/monarchLexer.ts", - "./vs/editor/standalone/common/monarch/monarchTypes.ts", - "./vs/editor/standalone/common/standaloneThemeService.ts", - "./vs/editor/standalone/common/themes.ts", - "./vs/editor/standalone/test/browser/simpleServices.test.ts", - "./vs/editor/test/browser/controller/imeTester.ts", - "./vs/editor/test/browser/editorTestServices.ts", - "./vs/editor/test/browser/testCodeEditor.ts", - "./vs/editor/test/browser/testCommand.ts", - "./vs/editor/test/browser/view/minimapFontCreator.ts", - "./vs/editor/test/browser/view/viewLayer.test.ts", - "./vs/editor/test/common/commentMode.ts", - "./vs/editor/test/common/config/commonEditorConfig.test.ts", - "./vs/editor/test/common/controller/cursorMoveHelper.test.ts", - "./vs/editor/test/common/core/characterClassifier.test.ts", - "./vs/editor/test/common/core/lineTokens.test.ts", - "./vs/editor/test/common/core/range.test.ts", - "./vs/editor/test/common/core/viewLineToken.ts", - "./vs/editor/test/common/editorTestUtils.ts", - "./vs/editor/test/common/mocks/mockMode.ts", - "./vs/editor/test/common/mocks/testConfiguration.ts", - "./vs/editor/test/common/model/benchmark/benchmarkUtils.ts", - "./vs/editor/test/common/model/benchmark/entry.ts", - "./vs/editor/test/common/model/benchmark/modelbuilder.benchmark.ts", - "./vs/editor/test/common/model/benchmark/operations.benchmark.ts", - "./vs/editor/test/common/model/benchmark/searchNReplace.benchmark.ts", - "./vs/editor/test/common/model/editableTextModelAuto.test.ts", - "./vs/editor/test/common/model/editableTextModelTestUtils.ts", - "./vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilder.test.ts", - "./vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils.ts", - "./vs/editor/test/common/model/model.test.ts", - "./vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts", - "./vs/editor/test/common/modes/languageConfiguration.test.ts", - "./vs/editor/test/common/modes/supports/characterPair.test.ts", - "./vs/editor/test/common/modes/supports/javascriptOnEnterRules.ts", - "./vs/editor/test/common/modes/supports/tokenization.test.ts", - "./vs/editor/test/common/modesTestUtils.ts", - "./vs/editor/test/common/services/languagesRegistry.test.ts", - "./vs/editor/test/common/view/minimapCharRendererFactory.ts", - "./vs/editor/test/common/view/overviewZoneManager.test.ts", - "./vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts", - "./vs/editor/test/common/viewLayout/lineDecorations.test.ts", - "./vs/editor/test/common/viewLayout/viewLineRenderer.test.ts", - "./vs/editor/test/common/viewLayout/whitespaceComputer.test.ts", - "./vs/editor/test/common/viewModel/characterHardWrappingLineMapper.test.ts", - "./vs/editor/test/common/viewModel/prefixSumComputer.test.ts", - "./vs/editor/test/common/viewModel/testViewModel.ts", - "./vs/editor/test/common/viewModel/viewModelDecorations.test.ts", - "./vs/editor/test/common/viewModel/viewModelImpl.test.ts", - "./vs/monaco.d.ts", - "./vs/nls.d.ts", - "./vs/nls.mock.ts", - "./vs/platform/actions/browser/menuItemActionItem.ts", - "./vs/platform/actions/common/actions.ts", - "./vs/platform/actions/common/menuService.ts", - "./vs/platform/actions/test/common/menuService.test.ts", - "./vs/platform/backup/common/backup.ts", - "./vs/platform/backup/electron-main/backupMainService.ts", - "./vs/platform/broadcast/electron-browser/broadcastService.ts", - "./vs/platform/clipboard/common/clipboardService.ts", - "./vs/platform/clipboard/electron-browser/clipboardService.ts", - "./vs/platform/commands/common/commands.ts", - "./vs/platform/commands/test/commands.test.ts", - "./vs/platform/configuration/common/configuration.ts", - "./vs/platform/configuration/common/configurationModels.ts", - "./vs/platform/configuration/common/configurationRegistry.ts", - "./vs/platform/configuration/node/configuration.ts", - "./vs/platform/configuration/node/configurationService.ts", - "./vs/platform/configuration/test/common/configuration.test.ts", - "./vs/platform/configuration/test/common/configurationModels.test.ts", - "./vs/platform/configuration/test/common/testConfigurationService.ts", - "./vs/platform/configuration/test/node/configurationService.test.ts", - "./vs/platform/contextkey/browser/contextKeyService.ts", - "./vs/platform/contextkey/common/contextkey.ts", - "./vs/platform/contextkey/test/common/contextkey.test.ts", - "./vs/platform/contextview/browser/contextMenuHandler.ts", - "./vs/platform/contextview/browser/contextMenuService.ts", - "./vs/platform/contextview/browser/contextView.ts", - "./vs/platform/contextview/browser/contextViewService.ts", - "./vs/platform/credentials/test/node/keytar.test.ts", - "./vs/platform/diagnostics/electron-main/diagnosticsService.ts", - "./vs/platform/dialogs/common/dialogs.ts", - "./vs/platform/dialogs/node/dialogIpc.ts", - "./vs/platform/download/common/download.ts", - "./vs/platform/download/node/downloadIpc.ts", - "./vs/platform/download/node/downloadService.ts", - "./vs/platform/driver/electron-browser/driver.ts", - "./vs/platform/driver/electron-main/driver.ts", - "./vs/platform/driver/node/driver.ts", - "./vs/platform/editor/common/editor.ts", - "./vs/platform/environment/common/environment.ts", - "./vs/platform/environment/node/argv.ts", - "./vs/platform/environment/node/environmentService.ts", - "./vs/platform/environment/test/node/environmentService.test.ts", - "./vs/platform/extensionManagement/common/extensionEnablementService.ts", - "./vs/platform/extensionManagement/common/extensionManagement.ts", - "./vs/platform/extensionManagement/common/extensionManagementUtil.ts", - "./vs/platform/extensionManagement/common/extensionNls.ts", - "./vs/platform/extensionManagement/node/extensionGalleryService.ts", - "./vs/platform/extensionManagement/node/extensionLifecycle.ts", - "./vs/platform/extensionManagement/node/extensionManagementIpc.ts", - "./vs/platform/extensionManagement/node/extensionManagementService.ts", - "./vs/platform/extensionManagement/node/extensionManagementUtil.ts", - "./vs/platform/extensionManagement/node/extensionsManifestCache.ts", - "./vs/platform/extensionManagement/node/multiExtensionManagement.ts", - "./vs/platform/extensionManagement/test/electron-browser/extensionManagement.test.ts", - "./vs/platform/extensions/common/extensionHost.ts", - "./vs/platform/extensions/common/extensions.ts", - "./vs/platform/extensions/node/extensionValidator.ts", - "./vs/platform/extensions/test/node/extensionValidator.test.ts", - "./vs/platform/files/common/files.ts", - "./vs/platform/files/node/files.ts", - "./vs/platform/files/test/files.test.ts", - "./vs/platform/history/common/history.ts", - "./vs/platform/history/electron-main/historyMainService.ts", - "./vs/platform/instantiation/common/descriptors.ts", - "./vs/platform/instantiation/common/extensions.ts", - "./vs/platform/instantiation/common/graph.ts", - "./vs/platform/instantiation/common/instantiation.ts", - "./vs/platform/instantiation/common/instantiationService.ts", - "./vs/platform/instantiation/common/serviceCollection.ts", - "./vs/platform/instantiation/node/instantiationService.ts", - "./vs/platform/instantiation/test/common/graph.test.ts", - "./vs/platform/instantiation/test/common/instantiationService.test.ts", - "./vs/platform/instantiation/test/common/instantiationServiceMock.ts", - "./vs/platform/integrity/common/integrity.ts", - "./vs/platform/integrity/node/integrityServiceImpl.ts", - "./vs/platform/issue/common/issue.ts", - "./vs/platform/issue/electron-main/issueService.ts", - "./vs/platform/issue/node/issueIpc.ts", - "./vs/platform/jsonschemas/common/jsonContributionRegistry.ts", - "./vs/platform/keybinding/common/abstractKeybindingService.ts", - "./vs/platform/keybinding/common/keybinding.ts", - "./vs/platform/keybinding/common/keybindingResolver.ts", - "./vs/platform/keybinding/common/keybindingsRegistry.ts", - "./vs/platform/keybinding/common/resolvedKeybindingItem.ts", - "./vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts", - "./vs/platform/keybinding/test/common/abstractKeybindingService.test.ts", - "./vs/platform/keybinding/test/common/keybindingLabels.test.ts", - "./vs/platform/keybinding/test/common/keybindingResolver.test.ts", - "./vs/platform/keybinding/test/common/mockKeybindingService.ts", - "./vs/platform/label/common/label.ts", - "./vs/platform/launch/electron-main/launchService.ts", - "./vs/platform/lifecycle/common/lifecycle.ts", - "./vs/platform/lifecycle/electron-browser/lifecycleService.ts", - "./vs/platform/lifecycle/electron-main/lifecycleMain.ts", - "./vs/platform/localizations/common/localizations.ts", - "./vs/platform/localizations/node/localizations.ts", - "./vs/platform/localizations/node/localizationsIpc.ts", - "./vs/platform/log/common/bufferLog.ts", - "./vs/platform/log/common/log.ts", - "./vs/platform/log/node/logIpc.ts", - "./vs/platform/log/node/spdlogService.ts", - "./vs/platform/markers/common/markerService.ts", - "./vs/platform/markers/common/markers.ts", - "./vs/platform/markers/test/common/markerService.test.ts", - "./vs/platform/menubar/common/menubar.ts", - "./vs/platform/menubar/electron-main/menubar.ts", - "./vs/platform/menubar/electron-main/menubarService.ts", - "./vs/platform/menubar/node/menubarIpc.ts", - "./vs/platform/node/minimalTranslations.ts", - "./vs/platform/node/package.ts", - "./vs/platform/node/product.ts", - "./vs/platform/node/test/zip.test.ts", - "./vs/platform/node/zip.ts", - "./vs/platform/notification/common/notification.ts", - "./vs/platform/notification/test/common/testNotificationService.ts", - "./vs/platform/opener/common/opener.ts", - "./vs/platform/output/node/outputAppender.ts", - "./vs/platform/progress/common/progress.ts", - "./vs/platform/quickOpen/common/quickOpen.ts", - "./vs/platform/quickinput/common/quickInput.ts", - "./vs/platform/registry/common/platform.ts", - "./vs/platform/registry/test/common/platform.test.ts", - "./vs/platform/remote/common/remoteAuthorityResolver.ts", - "./vs/platform/remote/common/remoteHosts.ts", - "./vs/platform/remote/electron-browser/remoteAuthorityResolverService.ts", - "./vs/platform/remote/node/remoteAgentConnection.ts", - "./vs/platform/remote/node/remoteAgentFileSystemChannel.ts", - "./vs/platform/request/electron-browser/requestService.ts", - "./vs/platform/request/electron-main/requestService.ts", - "./vs/platform/request/node/request.ts", - "./vs/platform/request/node/requestService.ts", - "./vs/platform/search/common/replace.ts", - "./vs/platform/search/common/search.ts", - "./vs/platform/search/test/common/replace.test.ts", - "./vs/platform/search/test/common/search.test.ts", - "./vs/platform/state/common/state.ts", - "./vs/platform/state/node/stateService.ts", - "./vs/platform/statusbar/common/statusbar.ts", - "./vs/platform/storage/common/storage.ts", - "./vs/platform/storage/node/storageIpc.ts", - "./vs/platform/storage/node/storageMainService.ts", - "./vs/platform/storage/node/storageService.ts", - "./vs/platform/telemetry/browser/errorTelemetry.ts", - "./vs/platform/telemetry/common/telemetry.ts", - "./vs/platform/telemetry/common/telemetryService.ts", - "./vs/platform/telemetry/common/telemetryUtils.ts", - "./vs/platform/telemetry/node/appInsightsAppender.ts", - "./vs/platform/telemetry/node/commonProperties.ts", - "./vs/platform/telemetry/node/telemetryIpc.ts", - "./vs/platform/telemetry/node/telemetryNodeUtils.ts", - "./vs/platform/telemetry/node/workbenchCommonProperties.ts", - "./vs/platform/telemetry/test/electron-browser/appInsightsAppender.test.ts", - "./vs/platform/telemetry/test/electron-browser/telemetryService.test.ts", - "./vs/platform/theme/common/colorRegistry.ts", - "./vs/platform/theme/common/styler.ts", - "./vs/platform/theme/common/themeService.ts", - "./vs/platform/theme/test/common/testThemeService.ts", - "./vs/platform/update/common/update.ts", - "./vs/platform/update/electron-main/abstractUpdateService.ts", - "./vs/platform/update/electron-main/updateService.darwin.ts", - "./vs/platform/update/electron-main/updateService.linux.ts", - "./vs/platform/update/electron-main/updateService.snap.ts", - "./vs/platform/update/electron-main/updateService.win32.ts", - "./vs/platform/update/node/update.config.contribution.ts", - "./vs/platform/update/node/updateIpc.ts", - "./vs/platform/url/common/url.ts", - "./vs/platform/url/common/urlService.ts", - "./vs/platform/url/electron-main/electronUrlListener.ts", - "./vs/platform/url/node/urlIpc.ts", - "./vs/platform/widget/browser/contextScopedHistoryWidget.ts", - "./vs/platform/widget/common/contextScopedWidget.ts", - "./vs/platform/windows/common/windows.ts", - "./vs/platform/windows/electron-browser/windowService.ts", - "./vs/platform/windows/electron-main/windows.ts", - "./vs/platform/windows/electron-main/windowsService.ts", - "./vs/platform/windows/node/windowsIpc.ts", - "./vs/platform/workbench/common/contextkeys.ts", - "./vs/platform/workspace/common/workspace.ts", - "./vs/platform/workspace/test/common/testWorkspace.ts", - "./vs/platform/workspace/test/common/workspace.test.ts", - "./vs/platform/workspaces/common/workspaces.ts", - "./vs/platform/workspaces/electron-main/workspacesMainService.ts", - "./vs/platform/workspaces/node/workspaces.ts", - "./vs/platform/workspaces/node/workspacesIpc.ts", - "./vs/vscode.d.ts", - "./vs/vscode.proposed.d.ts", - "./vs/workbench/api/node/extHostExtensionActivator.ts", - "./vs/workbench/api/node/extHostSearch.fileIndex.ts", - "./vs/workbench/api/node/extHostTypes.ts", - "./vs/workbench/api/shared/editor.ts", - "./vs/workbench/api/shared/tasks.ts", - "./vs/workbench/browser/actions/toggleActivityBarVisibility.ts", - "./vs/workbench/browser/actions/toggleCenteredLayout.ts", - "./vs/workbench/browser/actions/toggleEditorLayout.ts", - "./vs/workbench/browser/actions/toggleSidebarPosition.ts", - "./vs/workbench/browser/actions/toggleSidebarVisibility.ts", - "./vs/workbench/browser/actions/toggleStatusbarVisibility.ts", - "./vs/workbench/browser/actions/toggleTabsVisibility.ts", - "./vs/workbench/browser/actions/toggleZenMode.ts", - "./vs/workbench/browser/composite.ts", - "./vs/workbench/browser/editor.ts", - "./vs/workbench/browser/panel.ts", - "./vs/workbench/browser/part.ts", - "./vs/workbench/browser/parts/editor/baseEditor.ts", - "./vs/workbench/browser/parts/editor/binaryDiffEditor.ts", - "./vs/workbench/browser/parts/editor/binaryEditor.ts", - "./vs/workbench/browser/parts/editor/editor.ts", - "./vs/workbench/browser/parts/editor/editorControl.ts", - "./vs/workbench/browser/parts/editor/editorWidgets.ts", - "./vs/workbench/browser/parts/editor/rangeDecorations.ts", - "./vs/workbench/browser/parts/editor/resourceViewer.ts", - "./vs/workbench/browser/parts/editor/sideBySideEditor.ts", - "./vs/workbench/browser/parts/editor/textEditor.ts", - "./vs/workbench/browser/parts/notifications/notificationsAlerts.ts", - "./vs/workbench/browser/parts/quickinput/quickInputBox.ts", - "./vs/workbench/browser/parts/quickinput/quickInputUtils.ts", - "./vs/workbench/browser/parts/quickopen/quickopen.ts", - "./vs/workbench/browser/parts/statusbar/statusbar.ts", - "./vs/workbench/browser/parts/statusbar/statusbarPart.ts", - "./vs/workbench/common/actions.ts", - "./vs/workbench/common/activity.ts", - "./vs/workbench/common/component.ts", - "./vs/workbench/common/composite.ts", - "./vs/workbench/common/contributions.ts", - "./vs/workbench/common/editor.ts", - "./vs/workbench/common/editor/binaryEditorModel.ts", - "./vs/workbench/common/editor/dataUriEditorInput.ts", - "./vs/workbench/common/editor/diffEditorModel.ts", - "./vs/workbench/common/editor/editorGroup.ts", - "./vs/workbench/common/extensionHostProtocol.ts", - "./vs/workbench/common/memento.ts", - "./vs/workbench/common/notifications.ts", - "./vs/workbench/common/panel.ts", - "./vs/workbench/common/resources.ts", - "./vs/workbench/common/theme.ts", - "./vs/workbench/common/viewlet.ts", - "./vs/workbench/common/views.ts", - "./vs/workbench/electron-browser/resources.ts", - "./vs/workbench/electron-browser/window.ts", - "./vs/workbench/parts/backup/common/backupRestorer.ts", - "./vs/workbench/parts/cli/electron-browser/cli.contribution.ts", - "./vs/workbench/parts/codeEditor/browser/menuPreventer.ts", - "./vs/workbench/parts/codeEditor/browser/simpleEditorOptions.ts", - "./vs/workbench/parts/codeEditor/electron-browser/accessibility.ts", - "./vs/workbench/parts/codeEditor/electron-browser/inspectKeybindings.ts", - "./vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts", - "./vs/workbench/parts/codeEditor/electron-browser/largeFileOptimizations.ts", - "./vs/workbench/parts/codeEditor/electron-browser/selectionClipboard.ts", - "./vs/workbench/parts/codeEditor/electron-browser/textMate/inspectTMScopes.ts", - "./vs/workbench/parts/codeEditor/electron-browser/toggleMinimap.ts", - "./vs/workbench/parts/codeEditor/electron-browser/toggleMultiCursorModifier.ts", - "./vs/workbench/parts/codeEditor/electron-browser/toggleRenderControlCharacter.ts", - "./vs/workbench/parts/codeEditor/electron-browser/toggleRenderWhitespace.ts", - "./vs/workbench/parts/codeEditor/electron-browser/toggleWordWrap.ts", - "./vs/workbench/parts/comments/common/commentModel.ts", - "./vs/workbench/parts/comments/electron-browser/commentGlyphWidget.ts", - "./vs/workbench/parts/debug/browser/debugANSIHandling.ts", - "./vs/workbench/parts/debug/browser/linkDetector.ts", - "./vs/workbench/parts/debug/node/telemetryApp.ts", - "./vs/workbench/parts/emmet/browser/actions/showEmmetCommands.ts", - "./vs/workbench/parts/emmet/browser/emmet.browser.contribution.ts", - "./vs/workbench/parts/emmet/electron-browser/actions/expandAbbreviation.ts", - "./vs/workbench/parts/emmet/electron-browser/emmet.contribution.ts", - "./vs/workbench/parts/emmet/electron-browser/emmetActions.ts", - "./vs/workbench/parts/emmet/test/electron-browser/emmetAction.test.ts", - "./vs/workbench/parts/execution/common/execution.ts", - "./vs/workbench/parts/execution/electron-browser/terminal.ts", - "./vs/workbench/parts/execution/electron-browser/terminalService.ts", - "./vs/workbench/parts/execution/test/electron-browser/terminalService.test.ts", - "./vs/workbench/parts/experiments/node/experimentService.ts", - "./vs/workbench/parts/extensions/common/extensionQuery.ts", - "./vs/workbench/parts/extensions/common/extensions.ts", - "./vs/workbench/parts/extensions/common/extensionsFileTemplate.ts", - "./vs/workbench/parts/extensions/common/extensionsInput.ts", - "./vs/workbench/parts/extensions/electron-browser/extensionsActivationProgress.ts", - "./vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts", - "./vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts", - "./vs/workbench/parts/extensions/test/common/extensionQuery.test.ts", - "./vs/workbench/parts/feedback/electron-browser/feedback.contribution.ts", - "./vs/workbench/parts/feedback/electron-browser/feedback.ts", - "./vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts", - "./vs/workbench/parts/files/common/explorerModel.ts", - "./vs/workbench/parts/files/common/files.ts", - "./vs/workbench/parts/files/electron-browser/views/explorerDecorationsProvider.ts", - "./vs/workbench/parts/localizations/electron-browser/localizationsActions.ts", - "./vs/workbench/parts/logs/common/logConstants.ts", - "./vs/workbench/parts/logs/electron-browser/logs.contribution.ts", - "./vs/workbench/parts/logs/electron-browser/logsActions.ts", - "./vs/workbench/parts/markers/electron-browser/constants.ts", - "./vs/workbench/parts/markers/electron-browser/markers.ts", - "./vs/workbench/parts/markers/electron-browser/markersFileDecorations.ts", - "./vs/workbench/parts/markers/electron-browser/markersFilterOptions.ts", - "./vs/workbench/parts/markers/electron-browser/markersModel.ts", - "./vs/workbench/parts/markers/electron-browser/markersPanelActions.ts", - "./vs/workbench/parts/markers/electron-browser/messages.ts", - "./vs/workbench/parts/markers/test/electron-browser/markersModel.test.ts", - "./vs/workbench/parts/outline/electron-browser/outline.ts", - "./vs/workbench/parts/output/common/output.ts", - "./vs/workbench/parts/output/common/outputLinkComputer.ts", - "./vs/workbench/parts/output/common/outputLinkProvider.ts", - "./vs/workbench/parts/preferences/browser/settingsWidgets.ts", - "./vs/workbench/parts/preferences/common/smartSnippetInserter.ts", - "./vs/workbench/parts/preferences/test/common/smartSnippetInserter.test.ts", - "./vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts", - "./vs/workbench/parts/scm/common/scm.ts", - "./vs/workbench/parts/scm/electron-browser/scmActivity.ts", - "./vs/workbench/parts/scm/electron-browser/scmMenus.ts", - "./vs/workbench/parts/scm/electron-browser/scmUtil.ts", - "./vs/workbench/parts/search/browser/patternInputWidget.ts", - "./vs/workbench/parts/search/browser/replaceContributions.ts", - "./vs/workbench/parts/search/browser/replaceService.ts", - "./vs/workbench/parts/search/common/constants.ts", - "./vs/workbench/parts/search/common/queryBuilder.ts", - "./vs/workbench/parts/search/common/replace.ts", - "./vs/workbench/parts/search/common/search.ts", - "./vs/workbench/parts/search/common/searchModel.ts", - "./vs/workbench/parts/search/test/browser/mockSearchTree.ts", - "./vs/workbench/parts/search/test/common/searchModel.test.ts", - "./vs/workbench/parts/search/test/common/searchResult.test.ts", - "./vs/workbench/parts/snippets/electron-browser/configureSnippets.ts", - "./vs/workbench/parts/snippets/electron-browser/snippetCompletionProvider.ts", - "./vs/workbench/parts/snippets/electron-browser/snippets.contribution.ts", - "./vs/workbench/parts/snippets/electron-browser/snippetsFile.ts", - "./vs/workbench/parts/snippets/electron-browser/snippetsService.ts", - "./vs/workbench/parts/snippets/test/electron-browser/snippetFile.test.ts", - "./vs/workbench/parts/snippets/test/electron-browser/snippetsRegistry.test.ts", - "./vs/workbench/parts/snippets/test/electron-browser/snippetsRewrite.test.ts", - "./vs/workbench/parts/snippets/test/electron-browser/snippetsService.test.ts", - "./vs/workbench/parts/splash/electron-browser/partsSplash.contribution.ts", - "./vs/workbench/parts/stats/node/stats.contribution.ts", - "./vs/workbench/parts/stats/node/workspaceStats.ts", - "./vs/workbench/parts/stats/test/workspaceStats.test.ts", - "./vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.ts", - "./vs/workbench/parts/surveys/electron-browser/nps.contribution.ts", - "./vs/workbench/parts/tasks/common/problemCollectors.ts", - "./vs/workbench/parts/tasks/common/problemMatcher.ts", - "./vs/workbench/parts/tasks/common/taskDefinitionRegistry.ts", - "./vs/workbench/parts/tasks/common/taskService.ts", - "./vs/workbench/parts/tasks/common/taskSystem.ts", - "./vs/workbench/parts/tasks/common/taskTemplates.ts", - "./vs/workbench/parts/tasks/common/tasks.ts", - "./vs/workbench/parts/tasks/electron-browser/jsonSchemaCommon.ts", - "./vs/workbench/parts/tasks/electron-browser/jsonSchema_v1.ts", - "./vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.ts", - "./vs/workbench/parts/tasks/electron-browser/runAutomaticTasks.ts", - "./vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts", - "./vs/workbench/parts/tasks/node/processRunnerDetector.ts", - "./vs/workbench/parts/tasks/node/processTaskSystem.ts", - "./vs/workbench/parts/tasks/node/taskConfiguration.ts", - "./vs/workbench/parts/tasks/node/tasks.ts", - "./vs/workbench/parts/tasks/test/common/problemMatcher.test.ts", - "./vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts", - "./vs/workbench/parts/terminal/browser/terminalFindWidget.ts", - "./vs/workbench/parts/terminal/browser/terminalTab.ts", - "./vs/workbench/parts/terminal/browser/terminalWidgetManager.ts", - "./vs/workbench/parts/terminal/common/terminal.ts", - "./vs/workbench/parts/terminal/common/terminalColorRegistry.ts", - "./vs/workbench/parts/terminal/common/terminalCommands.ts", - "./vs/workbench/parts/terminal/common/terminalMenu.ts", - "./vs/workbench/parts/terminal/common/terminalService.ts", - "./vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts", - "./vs/workbench/parts/terminal/electron-browser/terminalInstance.ts", - "./vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.ts", - "./vs/workbench/parts/terminal/electron-browser/terminalProcessManager.ts", - "./vs/workbench/parts/terminal/node/terminal.ts", - "./vs/workbench/parts/terminal/node/terminalCommandTracker.ts", - "./vs/workbench/parts/terminal/node/terminalEnvironment.ts", - "./vs/workbench/parts/terminal/node/terminalProcess.ts", - "./vs/workbench/parts/terminal/node/terminalProcessExtHostProxy.ts", - "./vs/workbench/parts/terminal/node/windowsShellHelper.ts", - "./vs/workbench/parts/terminal/test/electron-browser/terminalColorRegistry.test.ts", - "./vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts", - "./vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts", - "./vs/workbench/parts/terminal/test/node/terminalCommandTracker.test.ts", - "./vs/workbench/parts/terminal/test/node/terminalEnvironment.test.ts", - "./vs/workbench/parts/url/electron-browser/url.contribution.ts", - "./vs/workbench/parts/webview/electron-browser/webviewProtocols.ts", - "./vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.contribution.ts", - "./vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.ts", - "./vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.ts", - "./vs/workbench/parts/welcome/gettingStarted/test/common/gettingStarted.test.ts", - "./vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts", - "./vs/workbench/parts/welcome/page/electron-browser/welcomePage.contribution.ts", - "./vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts", - "./vs/workbench/parts/welcome/walkThrough/electron-browser/editor/editorWalkThrough.ts", - "./vs/workbench/parts/welcome/walkThrough/electron-browser/walkThrough.contribution.ts", - "./vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughActions.ts", - "./vs/workbench/parts/welcome/walkThrough/electron-browser/walkThroughPart.ts", - "./vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts", - "./vs/workbench/parts/welcome/walkThrough/node/walkThroughInput.ts", - "./vs/workbench/parts/welcome/walkThrough/node/walkThroughUtils.ts", - "./vs/workbench/services/actions/electron-browser/menusExtensionPoint.ts", - "./vs/workbench/services/activity/common/activity.ts", - "./vs/workbench/services/backup/common/backup.ts", - "./vs/workbench/services/backup/node/backupFileService.ts", - "./vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts", - "./vs/workbench/services/codeEditor/browser/codeEditorService.ts", - "./vs/workbench/services/commands/common/commandService.ts", - "./vs/workbench/services/commands/test/common/commandService.test.ts", - "./vs/workbench/services/configuration/common/configuration.ts", - "./vs/workbench/services/configuration/common/configurationExtensionPoint.ts", - "./vs/workbench/services/configuration/common/configurationModels.ts", - "./vs/workbench/services/configuration/common/jsonEditing.ts", - "./vs/workbench/services/configuration/node/jsonEditingService.ts", - "./vs/workbench/services/configuration/test/common/configurationModels.test.ts", - "./vs/workbench/services/configurationResolver/common/configurationResolver.ts", - "./vs/workbench/services/configurationResolver/common/configurationResolverSchema.ts", - "./vs/workbench/services/configurationResolver/common/configurationResolverUtils.ts", - "./vs/workbench/services/contextview/electron-browser/contextmenuService.ts", - "./vs/workbench/services/crashReporter/electron-browser/crashReporterService.ts", - "./vs/workbench/services/decorations/browser/decorations.ts", - "./vs/workbench/services/decorations/browser/decorationsService.ts", - "./vs/workbench/services/decorations/test/browser/decorationsService.test.ts", - "./vs/workbench/services/dialogs/electron-browser/dialogService.ts", - "./vs/workbench/services/editor/common/editorService.ts", - "./vs/workbench/services/extensions/common/extensions.ts", - "./vs/workbench/services/extensions/common/extensionsRegistry.ts", - "./vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts", - "./vs/workbench/services/extensions/electron-browser/extensionHostProfiler.ts", - "./vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts", - "./vs/workbench/services/extensions/electron-browser/runtimeExtensionsInput.ts", - "./vs/workbench/services/extensions/node/extensionDescriptionRegistry.ts", - "./vs/workbench/services/extensions/node/extensionManagementServerService.ts", - "./vs/workbench/services/extensions/node/extensionPoints.ts", - "./vs/workbench/services/extensions/node/lazyPromise.ts", - "./vs/workbench/services/extensions/node/proxyIdentifier.ts", - "./vs/workbench/services/extensions/node/rpcProtocol.ts", - "./vs/workbench/services/extensions/test/node/rpcProtocol.test.ts", - "./vs/workbench/services/files/electron-browser/encoding.ts", - "./vs/workbench/services/files/node/watcher/common.ts", - "./vs/workbench/services/files/node/watcher/nsfw/nsfwWatcherService.ts", - "./vs/workbench/services/files/node/watcher/nsfw/test/nsfwWatcherService.test.ts", - "./vs/workbench/services/files/node/watcher/nsfw/watcher.ts", - "./vs/workbench/services/files/node/watcher/nsfw/watcherApp.ts", - "./vs/workbench/services/files/node/watcher/nsfw/watcherIpc.ts", - "./vs/workbench/services/files/node/watcher/nsfw/watcherService.ts", - "./vs/workbench/services/files/node/watcher/unix/chokidarWatcherService.ts", - "./vs/workbench/services/files/node/watcher/unix/test/chockidarWatcherService.test.ts", - "./vs/workbench/services/files/node/watcher/unix/watcher.ts", - "./vs/workbench/services/files/node/watcher/unix/watcherApp.ts", - "./vs/workbench/services/files/node/watcher/unix/watcherIpc.ts", - "./vs/workbench/services/files/node/watcher/unix/watcherService.ts", - "./vs/workbench/services/files/node/watcher/win32/csharpWatcherService.ts", - "./vs/workbench/services/files/node/watcher/win32/watcherService.ts", - "./vs/workbench/services/files/test/electron-browser/utils.ts", - "./vs/workbench/services/files/test/electron-browser/watcher.test.ts", - "./vs/workbench/services/group/common/editorGroupsService.ts", - "./vs/workbench/services/hash/common/hashService.ts", - "./vs/workbench/services/hash/node/hashService.ts", - "./vs/workbench/services/history/common/history.ts", - "./vs/workbench/services/history/electron-browser/history.ts", - "./vs/workbench/services/issue/common/issue.ts", - "./vs/workbench/services/issue/electron-browser/workbenchIssueService.ts", - "./vs/workbench/services/jsonschemas/common/jsonValidationExtensionPoint.ts", - "./vs/workbench/services/keybinding/common/keybindingIO.ts", - "./vs/workbench/services/keybinding/common/keyboardMapper.ts", - "./vs/workbench/services/keybinding/common/macLinuxFallbackKeyboardMapper.ts", - "./vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts", - "./vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts", - "./vs/workbench/services/keybinding/electron-browser/keybindingService.ts", - "./vs/workbench/services/keybinding/test/keybindingIO.test.ts", - "./vs/workbench/services/keybinding/test/keyboardMapperTestUtils.ts", - "./vs/workbench/services/keybinding/test/macLinuxFallbackKeyboardMapper.test.ts", - "./vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts", - "./vs/workbench/services/keybinding/test/windowsKeyboardMapper.test.ts", - "./vs/workbench/services/mode/common/workbenchModeService.ts", - "./vs/workbench/services/notification/common/notificationService.ts", - "./vs/workbench/services/panel/common/panelService.ts", - "./vs/workbench/services/part/common/partService.ts", - "./vs/workbench/services/preferences/common/keybindingsEditorModel.ts", - "./vs/workbench/services/preferences/test/common/keybindingsEditorModel.test.ts", - "./vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts", - "./vs/workbench/services/remote/node/remoteAgentEnvironmentChannel.ts", - "./vs/workbench/services/remote/node/remoteAgentService.ts", - "./vs/workbench/services/scm/common/scm.ts", - "./vs/workbench/services/scm/common/scmService.ts", - "./vs/workbench/services/search/common/searchHelpers.ts", - "./vs/workbench/services/search/node/fileSearch.ts", - "./vs/workbench/services/search/node/fileSearchManager.ts", - "./vs/workbench/services/search/node/legacy/rawLegacyTextSearchService.ts", - "./vs/workbench/services/search/node/legacy/search.ts", - "./vs/workbench/services/search/node/legacy/textSearch.ts", - "./vs/workbench/services/search/node/legacy/textSearchWorkerProvider.ts", - "./vs/workbench/services/search/node/legacy/worker/searchWorker.ts", - "./vs/workbench/services/search/node/legacy/worker/searchWorkerApp.ts", - "./vs/workbench/services/search/node/legacy/worker/searchWorkerIpc.ts", - "./vs/workbench/services/search/node/rawSearchService.ts", - "./vs/workbench/services/search/node/ripgrepFileSearch.ts", - "./vs/workbench/services/search/node/ripgrepSearchProvider.ts", - "./vs/workbench/services/search/node/ripgrepSearchUtils.ts", - "./vs/workbench/services/search/node/ripgrepTextSearchEngine.ts", - "./vs/workbench/services/search/node/search.ts", - "./vs/workbench/services/search/node/searchApp.ts", - "./vs/workbench/services/search/node/searchHistoryService.ts", - "./vs/workbench/services/search/node/searchIpc.ts", - "./vs/workbench/services/search/node/textSearchAdapter.ts", - "./vs/workbench/services/search/node/textSearchManager.ts", - "./vs/workbench/services/search/test/common/searchHelpers.test.ts", - "./vs/workbench/services/search/test/node/ripgrepFileSearch.test.ts", - "./vs/workbench/services/search/test/node/ripgrepTextSearchEngine.test.ts", - "./vs/workbench/services/search/test/node/search.test.ts", - "./vs/workbench/services/search/test/node/textSearch.integrationTest.ts", - "./vs/workbench/services/search/test/node/textSearchManager.test.ts", - "./vs/workbench/services/textMate/electron-browser/TMGrammars.ts", - "./vs/workbench/services/textMate/electron-browser/TMHelper.ts", - "./vs/workbench/services/textMate/electron-browser/TMSyntax.ts", - "./vs/workbench/services/textMate/electron-browser/textMateService.ts", - "./vs/workbench/services/textfile/common/textfiles.ts", - "./vs/workbench/services/textfile/electron-browser/textResourcePropertiesService.ts", - "./vs/workbench/services/themes/common/colorExtensionPoint.ts", - "./vs/workbench/services/themes/common/colorThemeSchema.ts", - "./vs/workbench/services/themes/common/fileIconThemeSchema.ts", - "./vs/workbench/services/themes/common/workbenchThemeService.ts", - "./vs/workbench/services/themes/electron-browser/fileIconThemeData.ts", - "./vs/workbench/services/themes/electron-browser/fileIconThemeStore.ts", - "./vs/workbench/services/title/common/titleService.ts", - "./vs/workbench/services/workspace/common/workspaceEditing.ts", - "./vs/workbench/test/common/editor/editorOptions.test.ts", - "./vs/workbench/test/common/notifications.test.ts", - "./vs/workbench/test/electron-browser/api/extHostTypes.test.ts", - "./vs/workbench/test/electron-browser/api/mock.ts" - ], - "exclude": [ - "./typings/require-monaco.d.ts" - ] -} \ No newline at end of file diff --git a/src/typings/chokidar.d.ts b/src/typings/chokidar.d.ts index 411080c2cc7..7f78ded23d4 100644 --- a/src/typings/chokidar.d.ts +++ b/src/typings/chokidar.d.ts @@ -5,84 +5,196 @@ declare module 'vscode-chokidar' { + // TypeScript Version: 3.0 + + import * as fs from "fs"; + import { EventEmitter } from "events"; + /** - * takes paths to be watched recursively and options + * The object's keys are all the directories (using absolute paths unless the `cwd` option was + * used), and the values are arrays of the names of the items contained in each directory. */ - export function watch(paths: string | string[], options: IOptions): FSWatcher; - - export interface IOptions { - - /** - * (regexp or function) files to be ignored. This function or regexp is tested against the whole path, not just filename. - * If it is a function with two arguments, it gets called twice per path - once with a single argument (the path), second time with two arguments (the path and the fs.Stats object of that path). - */ - ignored?: any; - - /** - * (default: false). Indicates whether the process should continue to run as long as files are being watched. - */ - persistent?: boolean; - - /** - * (default: false). Indicates whether to watch files that don't have read permissions. - */ - ignorePermissionErrors?: boolean; - - /** - * (default: false). Indicates whether chokidar should ignore the initial add events or not. - */ - ignoreInitial?: boolean; - - /** - * (default: 100). Interval of file system polling. - */ - interval?: number; - - /** - * (default: 300). Interval of file system polling for binary files (see extensions in src/is-binary). - */ - binaryInterval?: number; - - /** - * (default: false on Windows, true on Linux and OS X). Whether to use fs.watchFile (backed by polling), or fs.watch. If polling leads to high CPU utilization, consider setting this to false. - */ - usePolling?: boolean; - - /** - * (default: true on OS X). Whether to use the fsevents watching interface if available. When set to true explicitly and fsevents is available this supercedes the usePolling setting. When set to false on OS X, usePolling: true becomes the default. - */ - useFsEvents?: boolean; - - /** - * (default: true). When false, only the symlinks themselves will be watched for changes instead of following the link references and bubbling events through the link's path. - */ - followSymlinks?: boolean; - - /** - * (default: false). If set to true then the strings passed to .watch() and .add() are treated as literal path names, even if they look like globs. - */ - disableGlobbing?: boolean; + export interface WatchedPaths { + [directory: string]: string[]; } - export interface FSWatcher { + export class FSWatcher extends EventEmitter implements fs.FSWatcher { - add(fileDirOrGlob: string): void; - add(filesDirsOrGlobs: Array): void; - - unwatch(fileDirOrGlob: string): void; - unwatch(filesDirsOrGlobs: Array): void; + readonly options?: WatchOptions; /** - * Listen for an FS event. Available events: add, addDir, change, unlink, unlinkDir, error. Additionally all is available which gets emitted for every non-error event. + * Constructs a new FSWatcher instance with optional WatchOptions parameter. */ - on(event: string, clb: (type: string, path: string) => void): void; - on(event: string, clb: (error: Error) => void): void; + constructor(options?: WatchOptions); + + /** + * Add files, directories, or glob patterns for tracking. Takes an array of strings or just one + * string. + */ + add(paths: string | string[]): void; + + /** + * Stop watching files, directories, or glob patterns. Takes an array of strings or just one + * string. + */ + unwatch(paths: string | string[]): void; + + /** + * Returns an object representing all the paths on the file system being watched by this + * `FSWatcher` instance. The object's keys are all the directories (using absolute paths unless + * the `cwd` option was used), and the values are arrays of the names of the items contained in + * each directory. + */ + getWatched(): WatchedPaths; /** * Removes all listeners from watched files. */ close(): void; - options: IOptions; + on(event: 'add' | 'addDir' | 'change', listener: (path: string, stats?: fs.Stats) => void): this; + + on(event: 'all', listener: (eventName: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir', path: string, stats?: fs.Stats) => void): this; + + /** + * Error occured + */ + on(event: 'error', listener: (error: Error) => void): this; + + /** + * Exposes the native Node `fs.FSWatcher events` + */ + on(event: 'raw', listener: (eventName: string, path: string, details: any) => void): this; + + /** + * Fires when the initial scan is complete + */ + on(event: 'ready', listener: () => void): this; + + on(event: 'unlink' | 'unlinkDir', listener: (path: string) => void): this; + + on(event: string, listener: (...args: any[]) => void): this; } + + export interface WatchOptions { + /** + * Indicates whether the process should continue to run as long as files are being watched. If + * set to `false` when using `fsevents` to watch, no more events will be emitted after `ready`, + * even if the process continues to run. + */ + persistent?: boolean; + + /** + * ([anymatch](https://github.com/es128/anymatch)-compatible definition) Defines files/paths to + * be ignored. The whole relative or absolute path is tested, not just filename. If a function + * with two arguments is provided, it gets called twice per path - once with a single argument + * (the path), second time with two arguments (the path and the + * [`fs.Stats`](http://nodejs.org/api/fs.html#fs_class_fs_stats) object of that path). + */ + ignored?: any; + + /** + * If set to `false` then `add`/`addDir` events are also emitted for matching paths while + * instantiating the watching as chokidar discovers these file paths (before the `ready` event). + */ + ignoreInitial?: boolean; + + /** + * When `false`, only the symlinks themselves will be watched for changes instead of following + * the link references and bubbling events through the link's path. + */ + followSymlinks?: boolean; + + /** + * The base directory from which watch `paths` are to be derived. Paths emitted with events will + * be relative to this. + */ + cwd?: string; + + /** + * If set to true then the strings passed to .watch() and .add() are treated as literal path + * names, even if they look like globs. Default: false. + */ + disableGlobbing?: boolean; + + /** + * Whether to use fs.watchFile (backed by polling), or fs.watch. If polling leads to high CPU + * utilization, consider setting this to `false`. It is typically necessary to **set this to + * `true` to successfully watch files over a network**, and it may be necessary to successfully + * watch files in other non-standard situations. Setting to `true` explicitly on OS X overrides + * the `useFsEvents` default. + */ + usePolling?: boolean; + + /** + * Whether to use the `fsevents` watching interface if available. When set to `true` explicitly + * and `fsevents` is available this supercedes the `usePolling` setting. When set to `false` on + * OS X, `usePolling: true` becomes the default. + */ + useFsEvents?: boolean; + + /** + * If relying upon the [`fs.Stats`](http://nodejs.org/api/fs.html#fs_class_fs_stats) object that + * may get passed with `add`, `addDir`, and `change` events, set this to `true` to ensure it is + * provided even in cases where it wasn't already available from the underlying watch events. + */ + alwaysStat?: boolean; + + /** + * If set, limits how many levels of subdirectories will be traversed. + */ + depth?: number; + + /** + * Interval of file system polling. + */ + interval?: number; + + /** + * Interval of file system polling for binary files. ([see list of binary extensions](https://gi + * thub.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json)) + */ + binaryInterval?: number; + + /** + * Indicates whether to watch files that don't have read permissions if possible. If watching + * fails due to `EPERM` or `EACCES` with this set to `true`, the errors will be suppressed + * silently. + */ + ignorePermissionErrors?: boolean; + + /** + * `true` if `useFsEvents` and `usePolling` are `false`). Automatically filters out artifacts + * that occur when using editors that use "atomic writes" instead of writing directly to the + * source file. If a file is re-added within 100 ms of being deleted, Chokidar emits a `change` + * event rather than `unlink` then `add`. If the default of 100 ms does not work well for you, + * you can override it by setting `atomic` to a custom value, in milliseconds. + */ + atomic?: boolean | number; + + /** + * can be set to an object in order to adjust timing params: + */ + awaitWriteFinish?: AwaitWriteFinishOptions | boolean; + } + + export interface AwaitWriteFinishOptions { + /** + * Amount of time in milliseconds for a file size to remain constant before emitting its event. + */ + stabilityThreshold?: number; + + /** + * File size polling interval. + */ + pollInterval?: number; + } + + /** + * produces an instance of `FSWatcher`. + */ + export function watch( + paths: string | string[], + options?: WatchOptions + ): FSWatcher; } \ No newline at end of file diff --git a/src/typings/electron.d.ts b/src/typings/electron.d.ts index d7682bfa180..5be0ac0e3fe 100644 --- a/src/typings/electron.d.ts +++ b/src/typings/electron.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Electron 3.0.13 +// Type definitions for Electron 4.2.7 // Project: http://electronjs.org/ // Definitions by: The Electron Team // Definitions: https://github.com/electron/electron-typescript-definitions @@ -86,7 +86,7 @@ declare namespace Electron { webviewTag: WebviewTag; } - interface AllElectron extends MainInterface, RendererInterface {} + interface AllElectron extends MainInterface, RendererInterface { } const app: App; const autoUpdater: AutoUpdater; @@ -119,7 +119,7 @@ declare namespace Electron { interface App extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/app + // Docs: http://electronjs.org/docs/api/app /** * Emitted when Chrome's accessibility support changes. This event fires when @@ -472,6 +472,100 @@ declare namespace Electron { once(event: 'ready', listener: (launchInfo: any) => void): this; addListener(event: 'ready', listener: (launchInfo: any) => void): this; removeListener(event: 'ready', listener: (launchInfo: any) => void): this; + /** + * Emitted when remote.getBuiltin() is called in the renderer process of + * webContents. Calling event.preventDefault() will prevent the module from being + * returned. Custom value can be returned by setting event.returnValue. + */ + on(event: 'remote-get-builtin', listener: (event: Event, + webContents: WebContents, + moduleName: string) => void): this; + once(event: 'remote-get-builtin', listener: (event: Event, + webContents: WebContents, + moduleName: string) => void): this; + addListener(event: 'remote-get-builtin', listener: (event: Event, + webContents: WebContents, + moduleName: string) => void): this; + removeListener(event: 'remote-get-builtin', listener: (event: Event, + webContents: WebContents, + moduleName: string) => void): this; + /** + * Emitted when remote.getCurrentWebContents() is called in the renderer process of + * webContents. Calling event.preventDefault() will prevent the object from being + * returned. Custom value can be returned by setting event.returnValue. + */ + on(event: 'remote-get-current-web-contents', listener: (event: Event, + webContents: WebContents) => void): this; + once(event: 'remote-get-current-web-contents', listener: (event: Event, + webContents: WebContents) => void): this; + addListener(event: 'remote-get-current-web-contents', listener: (event: Event, + webContents: WebContents) => void): this; + removeListener(event: 'remote-get-current-web-contents', listener: (event: Event, + webContents: WebContents) => void): this; + /** + * Emitted when remote.getCurrentWindow() is called in the renderer process of + * webContents. Calling event.preventDefault() will prevent the object from being + * returned. Custom value can be returned by setting event.returnValue. + */ + on(event: 'remote-get-current-window', listener: (event: Event, + webContents: WebContents) => void): this; + once(event: 'remote-get-current-window', listener: (event: Event, + webContents: WebContents) => void): this; + addListener(event: 'remote-get-current-window', listener: (event: Event, + webContents: WebContents) => void): this; + removeListener(event: 'remote-get-current-window', listener: (event: Event, + webContents: WebContents) => void): this; + /** + * Emitted when remote.getGlobal() is called in the renderer process of + * webContents. Calling event.preventDefault() will prevent the global from being + * returned. Custom value can be returned by setting event.returnValue. + */ + on(event: 'remote-get-global', listener: (event: Event, + webContents: WebContents, + globalName: string) => void): this; + once(event: 'remote-get-global', listener: (event: Event, + webContents: WebContents, + globalName: string) => void): this; + addListener(event: 'remote-get-global', listener: (event: Event, + webContents: WebContents, + globalName: string) => void): this; + removeListener(event: 'remote-get-global', listener: (event: Event, + webContents: WebContents, + globalName: string) => void): this; + /** + * Emitted when .getWebContents() is called in the renderer process of + * webContents. Calling event.preventDefault() will prevent the object from being + * returned. Custom value can be returned by setting event.returnValue. + */ + on(event: 'remote-get-guest-web-contents', listener: (event: Event, + webContents: WebContents, + guestWebContents: WebContents) => void): this; + once(event: 'remote-get-guest-web-contents', listener: (event: Event, + webContents: WebContents, + guestWebContents: WebContents) => void): this; + addListener(event: 'remote-get-guest-web-contents', listener: (event: Event, + webContents: WebContents, + guestWebContents: WebContents) => void): this; + removeListener(event: 'remote-get-guest-web-contents', listener: (event: Event, + webContents: WebContents, + guestWebContents: WebContents) => void): this; + /** + * Emitted when remote.require() is called in the renderer process of webContents. + * Calling event.preventDefault() will prevent the module from being returned. + * Custom value can be returned by setting event.returnValue. + */ + on(event: 'remote-require', listener: (event: Event, + webContents: WebContents, + moduleName: string) => void): this; + once(event: 'remote-require', listener: (event: Event, + webContents: WebContents, + moduleName: string) => void): this; + addListener(event: 'remote-require', listener: (event: Event, + webContents: WebContents, + moduleName: string) => void): this; + removeListener(event: 'remote-require', listener: (event: Event, + webContents: WebContents, + moduleName: string) => void): this; /** * This event will be emitted inside the primary instance of your application when * a second instance has been executed. argv is an Array of the second instance's @@ -690,6 +784,11 @@ declare namespace Electron { * is ready. */ enableMixedSandbox(): void; + /** + * Enables full sandbox mode on the app. This method can only be called before app + * is ready. + */ + enableSandbox(): void; /** * Exits immediately with exitCode. exitCode defaults to 0. All windows will be * closed immediately without asking user and the before-quit and will-quit events @@ -709,13 +808,22 @@ declare namespace Electron { * Fetches a path's associated icon. On Windows, there a 2 kinds of icons: On Linux * and macOS, icons depend on the application associated with file mime type. */ - getFileIcon(path: string, options: FileIconOptions, callback: (error: Error, icon: NativeImage) => void): void; + getFileIcon(path: string, callback: (error: Error, icon: NativeImage) => void): void; /** * Fetches a path's associated icon. On Windows, there a 2 kinds of icons: On Linux * and macOS, icons depend on the application associated with file mime type. */ - getFileIcon(path: string, callback: (error: Error, icon: NativeImage) => void): void; + getFileIcon(path: string, options: FileIconOptions, callback: (error: Error, icon: NativeImage) => void): void; getGPUFeatureStatus(): GPUFeatureStatus; + /** + * For infoType equal to complete: Promise is fulfilled with Object containing all + * the GPU Information as in chromium's GPUInfo object. This includes the version + * and driver information that's shown on chrome://gpu page. For infoType equal to + * basic: Promise is fulfilled with Object containing fewer attributes than when + * requested with complete. Here's an example of basic response: Using basic should + * be preferred if only basic information like vendorId or driverId is needed. + */ + getGPUInfo(infoType: string): Promise; getJumpListSettings(): JumpListSettings; /** * To set the locale, you'll want to use a command line switch at app startup, @@ -754,7 +862,7 @@ declare namespace Electron { /** * Imports the certificate in pkcs12 format into the platform certificate store. * callback is called with the result of import operation, a value of 0 indicates - * success while any other value indicates failure according to chromium + * success while any other value indicates failure according to Chromium * net_error_list. */ importCertificate(options: ImportCertificateOptions, callback: (result: number) => void): void; @@ -843,9 +951,9 @@ declare namespace Electron { setAboutPanelOptions(options: AboutPanelOptionsOptions): void; /** * Manually enables Chrome's accessibility support, allowing to expose - * accessibility switch to users in application settings. - * https://www.chromium.org/developers/design-documents/accessibility for more - * details. Disabled by default. Note: Rendering accessibility tree can + * accessibility switch to users in application settings. See Chromium's + * accessibility docs for more details. Disabled by default. This API must be + * called after the ready event is emitted. Note: Rendering accessibility tree can * significantly affect the performance of your app. It should not be enabled by * default. */ @@ -929,7 +1037,12 @@ declare namespace Electron { */ show(): void; /** - * Start accessing a security scoped resource. With this method electron + * Show the about panel with the values defined in the app's .plist file or with + * the options set via app.setAboutPanelOptions(options). + */ + showAboutPanel(): void; + /** + * Start accessing a security scoped resource. With this method Electron * applications that are packaged for the Mac App Store may reach outside their * sandbox to access files chosen by the user. See Apple's documentation for a * description of how this system works. @@ -940,7 +1053,7 @@ declare namespace Electron { * userInfo into its current userInfo dictionary. */ updateCurrentActivity(type: string, userInfo: any): void; - whenReady(): Promise; + whenReady(): Promise; commandLine: CommandLine; dock: Dock; /** @@ -949,11 +1062,19 @@ declare namespace Electron { * production environments. */ isPackaged?: boolean; + /** + * A String which is the user agent string Electron will use as a global fallback. + * This is the user agent that will be used when no user agent is set at the + * webContents or session level. Useful for ensuring your entire app has the same + * user agent. Set to a custom value as early as possible in your apps + * initialization to ensure that your overridden value is used. + */ + userAgentFallback?: string; } interface AutoUpdater extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/auto-updater + // Docs: http://electronjs.org/docs/api/auto-updater /** * This event is emitted after a user calls quitAndInstall(). When this API is @@ -990,7 +1111,9 @@ declare namespace Electron { removeListener(event: 'update-available', listener: Function): this; /** * Emitted when an update has been downloaded. On Windows only releaseName is - * available. + * available. Note: It is not strictly necessary to handle this event. A + * successfully downloaded update will still be applied the next time the + * application starts. */ on(event: 'update-downloaded', listener: (event: Event, releaseNotes: string, @@ -1029,10 +1152,10 @@ declare namespace Electron { * Restarts the app and installs the update after it has been downloaded. It should * only be called after update-downloaded has been emitted. Under the hood calling * autoUpdater.quitAndInstall() will close all application windows first, and - * automatically call app.quit() after all windows have been closed. Note: If the - * application is quit without calling this API after the update-downloaded event - * has been emitted, the application will still be replaced by the updated one on - * the next run. + * automatically call app.quit() after all windows have been closed. Note: It is + * not strictly necessary to call this function to apply an update, as a + * successfully downloaded update will always be applied the next time the + * application starts. */ quitAndInstall(): void; /** @@ -1043,7 +1166,7 @@ declare namespace Electron { interface BluetoothDevice { - // Docs: http://electron.atom.io/docs/api/structures/bluetooth-device + // Docs: http://electronjs.org/docs/api/structures/bluetooth-device deviceId: string; deviceName: string; @@ -1051,11 +1174,11 @@ declare namespace Electron { class BrowserView extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/browser-view + // Docs: http://electronjs.org/docs/api/browser-view constructor(options?: BrowserViewConstructorOptions); static fromId(id: number): BrowserView; - static fromWebContents(webContents: WebContents): BrowserView | null; + static fromWebContents(webContents: WebContents): (BrowserView) | (null); static getAllViews(): BrowserView[]; /** * Force closing the view, the unload and beforeunload events won't be emitted for @@ -1076,8 +1199,19 @@ declare namespace Electron { class BrowserWindow extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/browser-window + // Docs: http://electronjs.org/docs/api/browser-window + /** + * Emitted when the window is set or unset to show always on top of other windows. + */ + on(event: 'always-on-top-changed', listener: (event: Event, + isAlwaysOnTop: boolean) => void): this; + once(event: 'always-on-top-changed', listener: (event: Event, + isAlwaysOnTop: boolean) => void): this; + addListener(event: 'always-on-top-changed', listener: (event: Event, + isAlwaysOnTop: boolean) => void): this; + removeListener(event: 'always-on-top-changed', listener: (event: Event, + isAlwaysOnTop: boolean) => void): this; /** * Emitted when an App Command is invoked. These are typically related to keyboard * media keys or browser commands, as well as the "Back" button built into some @@ -1204,16 +1338,21 @@ declare namespace Electron { removeListener(event: 'new-window-for-tab', listener: Function): this; /** * Emitted when the document changed its title, calling event.preventDefault() will - * prevent the native window's title from changing. + * prevent the native window's title from changing. explicitSet is false when title + * is synthesized from file url. */ on(event: 'page-title-updated', listener: (event: Event, - title: string) => void): this; + title: string, + explicitSet: boolean) => void): this; once(event: 'page-title-updated', listener: (event: Event, - title: string) => void): this; + title: string, + explicitSet: boolean) => void): this; addListener(event: 'page-title-updated', listener: (event: Event, - title: string) => void): this; + title: string, + explicitSet: boolean) => void): this; removeListener(event: 'page-title-updated', listener: (event: Event, - title: string) => void): this; + title: string, + explicitSet: boolean) => void): this; /** * Emitted when the web page has been rendered (while not being shown) and window * can be displayed without a visual flash. @@ -1223,7 +1362,7 @@ declare namespace Electron { addListener(event: 'ready-to-show', listener: Function): this; removeListener(event: 'ready-to-show', listener: Function): this; /** - * Emitted when the window is being resized. + * Emitted after the window has been resized. */ on(event: 'resize', listener: Function): this; once(event: 'resize', listener: Function): this; @@ -1318,6 +1457,58 @@ declare namespace Electron { once(event: 'unresponsive', listener: Function): this; addListener(event: 'unresponsive', listener: Function): this; removeListener(event: 'unresponsive', listener: Function): this; + /** + * Emitted before the window is moved. Calling event.preventDefault() will prevent + * the window from being moved. Note that this is only emitted when the window is + * being resized manually. Resizing the window with setBounds/setSize will not emit + * this event. + */ + on(event: 'will-move', listener: (event: Event, + /** + * ` Location the window is being moved to. + */ + newBounds: Rectangle) => void): this; + once(event: 'will-move', listener: (event: Event, + /** + * ` Location the window is being moved to. + */ + newBounds: Rectangle) => void): this; + addListener(event: 'will-move', listener: (event: Event, + /** + * ` Location the window is being moved to. + */ + newBounds: Rectangle) => void): this; + removeListener(event: 'will-move', listener: (event: Event, + /** + * ` Location the window is being moved to. + */ + newBounds: Rectangle) => void): this; + /** + * Emitted before the window is resized. Calling event.preventDefault() will + * prevent the window from being resized. Note that this is only emitted when the + * window is being resized manually. Resizing the window with setBounds/setSize + * will not emit this event. + */ + on(event: 'will-resize', listener: (event: Event, + /** + * ` Size the window is being resized to. + */ + newBounds: Rectangle) => void): this; + once(event: 'will-resize', listener: (event: Event, + /** + * ` Size the window is being resized to. + */ + newBounds: Rectangle) => void): this; + addListener(event: 'will-resize', listener: (event: Event, + /** + * ` Size the window is being resized to. + */ + newBounds: Rectangle) => void): this; + removeListener(event: 'will-resize', listener: (event: Event, + /** + * ` Size the window is being resized to. + */ + newBounds: Rectangle) => void): this; constructor(options?: BrowserWindowConstructorOptions); /** * Adds DevTools extension located at path, and returns extension's name. The @@ -1335,7 +1526,7 @@ declare namespace Electron { * This API cannot be called before the ready event of the app module is emitted. */ static addExtension(path: string): void; - static fromBrowserView(browserView: BrowserView): BrowserWindow | null; + static fromBrowserView(browserView: BrowserView): (BrowserWindow) | (null); static fromId(id: number): BrowserWindow; static fromWebContents(webContents: WebContents): BrowserWindow; static getAllWindows(): BrowserWindow[]; @@ -1349,7 +1540,7 @@ declare namespace Electron { * emitted. */ static getExtensions(): Extensions; - static getFocusedWindow(): BrowserWindow | null; + static getFocusedWindow(): (BrowserWindow) | (null); /** * Remove a DevTools extension by name. Note: This API cannot be called before the * ready event of the app module is emitted. @@ -1411,7 +1602,7 @@ declare namespace Electron { * Note: The BrowserView API is currently experimental and may change or be removed * in future Electron releases. */ - getBrowserView(): BrowserView | null; + getBrowserView(): (BrowserView) | (null); getChildWindows(): BrowserWindow[]; getContentBounds(): Rectangle; getContentSize(): number[]; @@ -1422,6 +1613,13 @@ declare namespace Electron { * (unsigned long) on Linux. */ getNativeWindowHandle(): Buffer; + /** + * Note: whatever the current state of the window : maximized, minimized or in + * fullscreen, this function always returns the position and size of the window in + * normal state. In normal state, getBounds and getNormalBounds returns the same + * Rectangle. + */ + getNormalBounds(): Rectangle; getOpacity(): number; getParentWindow(): BrowserWindow; getPosition(): number[]; @@ -1473,6 +1671,7 @@ declare namespace Electron { * On Linux always returns true. */ isMovable(): boolean; + isNormal(): boolean; isResizable(): boolean; isSimpleFullScreen(): boolean; isVisible(): boolean; @@ -1485,7 +1684,7 @@ declare namespace Electron { * Same as webContents.loadFile, filePath should be a path to an HTML file relative * to the root of your application. See the webContents docs for more information. */ - loadFile(filePath: string): void; + loadFile(filePath: string, options?: LoadFileOptions): void; /** * Same as webContents.loadURL(url[, options]). The url can be a remote address * (e.g. http://) or a path to a local HTML file using the file:// protocol. To @@ -1579,7 +1778,12 @@ declare namespace Electron { */ setAutoHideMenuBar(hide: boolean): void; /** - * Resizes and moves the window to the supplied bounds + * Sets the background color of the window. See Setting backgroundColor. + */ + setBackgroundColor(backgroundColor: string): void; + /** + * Resizes and moves the window to the supplied bounds. Any properties that are not + * supplied will default to their current values. */ setBounds(bounds: Rectangle, animate?: boolean): void; setBrowserView(browserView: BrowserView): void; @@ -1655,7 +1859,7 @@ declare namespace Electron { * Sets the menu as the window's menu bar, setting it to null will remove the menu * bar. */ - setMenu(menu: Menu | null): void; + setMenu(menu: (Menu) | (null)): void; /** * Sets whether the menu bar should be visible. If the menu bar is auto-hide, users * can still bring up the menu bar by pressing the single Alt key. @@ -1682,7 +1886,7 @@ declare namespace Electron { * Sets a 16 x 16 pixel overlay onto the current taskbar icon, usually used to * convey some sort of application status or to passively notify the user. */ - setOverlayIcon(overlay: NativeImage | null, description: string): void; + setOverlayIcon(overlay: (NativeImage) | (null), description: string): void; /** * Sets parent as current window's parent window, passing null will turn current * window into a top-level window. @@ -1754,7 +1958,8 @@ declare namespace Electron { /** * Sets the region of the window to show as the thumbnail image displayed when * hovering over the window in the taskbar. You can reset the thumbnail to be the - * entire window by specifying an empty region: {x: 0, y: 0, width: 0, height: 0}. + * entire window by specifying an empty region: { x: 0, y: 0, width: 0, height: 0 + * }. */ setThumbnailClip(region: Rectangle): void; /** @@ -1782,7 +1987,12 @@ declare namespace Electron { * Sets whether the window should be visible on all workspaces. Note: This API does * nothing on Windows. */ - setVisibleOnAllWorkspaces(visible: boolean): void; + setVisibleOnAllWorkspaces(visible: boolean, options?: VisibleOnAllWorkspacesOptions): void; + /** + * Sets whether the window traffic light buttons should be visible. This cannot be + * called when titleBarStyle is set to customButtonsOnHover. + */ + setWindowButtonVisibility(visible: boolean): void; /** * Shows and gives focus to the window. */ @@ -1818,7 +2028,7 @@ declare namespace Electron { class BrowserWindowProxy extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/browser-window-proxy + // Docs: http://electronjs.org/docs/api/browser-window-proxy /** * Removes focus from the child window. @@ -1851,7 +2061,7 @@ declare namespace Electron { interface Certificate { - // Docs: http://electron.atom.io/docs/api/structures/certificate + // Docs: http://electronjs.org/docs/api/structures/certificate /** * PEM encoded data @@ -1897,37 +2107,37 @@ declare namespace Electron { interface CertificatePrincipal { - // Docs: http://electron.atom.io/docs/api/structures/certificate-principal + // Docs: http://electronjs.org/docs/api/structures/certificate-principal /** - * Common Name + * Common Name. */ commonName: string; /** - * Country or region + * Country or region. */ country: string; /** - * Locality + * Locality. */ locality: string; /** - * Organization names + * Organization names. */ organizations: string[]; /** - * Organization Unit names + * Organization Unit names. */ organizationUnits: string[]; /** - * State or province + * State or province. */ state: string; } class ClientRequest extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/client-request + // Docs: http://electronjs.org/docs/api/client-request /** * Emitted when the request is aborted. The abort event will not be fired if the @@ -2045,7 +2255,7 @@ declare namespace Electron { * Sends the last chunk of the request data. Subsequent write or end operations * will not be allowed. The finish event is emitted just after the end operation. */ - end(chunk?: string | Buffer, encoding?: string, callback?: Function): void; + end(chunk?: (string) | (Buffer), encoding?: string, callback?: Function): void; /** * Continues any deferred redirection request when the redirection mode is manual. */ @@ -2078,13 +2288,13 @@ declare namespace Electron { * issued on the wire. After the first write operation, it is not allowed to add or * remove a custom header. */ - write(chunk: string | Buffer, encoding?: string, callback?: Function): void; + write(chunk: (string) | (Buffer), encoding?: string, callback?: Function): void; chunkedEncoding: boolean; } interface Clipboard extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/clipboard + // Docs: http://electronjs.org/docs/api/clipboard availableFormats(type?: string): string[]; /** @@ -2144,7 +2354,7 @@ declare namespace Electron { interface ContentTracing extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/content-tracing + // Docs: http://electronjs.org/docs/api/content-tracing /** * Get the current monitoring traced data. Child processes typically cache trace @@ -2179,20 +2389,9 @@ declare namespace Electron { * Start recording on all processes. Recording begins immediately locally and * asynchronously on child processes as soon as they receive the EnableRecording * request. The callback will be called once all child processes have acknowledged - * the startRecording request. categoryFilter is a filter to control what category - * groups should be traced. A filter can have an optional - prefix to exclude - * category groups that contain a matching category. Having both included and - * excluded category patterns in the same list is not supported. Examples: - * traceOptions controls what kind of tracing is enabled, it is a comma-delimited - * list. Possible options are: The first 3 options are trace recording modes and - * hence mutually exclusive. If more than one trace recording modes appear in the - * traceOptions string, the last one takes precedence. If none of the trace - * recording modes are specified, recording mode is record-until-full. The trace - * option will first be reset to the default option (record_mode set to - * record-until-full, enable_sampling and enable_systrace set to false) before - * options parsed from traceOptions are applied on it. + * the startRecording request. */ - startRecording(options: StartRecordingOptions, callback: Function): void; + startRecording(options: (TraceCategoriesAndOptions) | (TraceConfig), callback: Function): void; /** * Stop monitoring on all processes. Once all child processes have acknowledged the * stopMonitoring request the callback is called. @@ -2214,10 +2413,11 @@ declare namespace Electron { interface Cookie { - // Docs: http://electron.atom.io/docs/api/structures/cookie + // Docs: http://electronjs.org/docs/api/structures/cookie /** - * The domain of the cookie. + * The domain of the cookie; this will be normalized with a preceding dot so that + * it's also valid for subdomains. */ domain?: string; /** @@ -2226,7 +2426,8 @@ declare namespace Electron { */ expirationDate?: number; /** - * Whether the cookie is a host-only cookie. + * Whether the cookie is a host-only cookie; this will only be true if no domain + * was passed. */ hostOnly?: boolean; /** @@ -2258,7 +2459,7 @@ declare namespace Electron { class Cookies extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/cookies + // Docs: http://electronjs.org/docs/api/cookies /** * Emitted when a cookie is changed because it was added, edited, removed, or @@ -2339,7 +2540,7 @@ declare namespace Electron { interface CPUUsage { - // Docs: http://electron.atom.io/docs/api/structures/cpu-usage + // Docs: http://electronjs.org/docs/api/structures/cpu-usage /** * The number of average idle cpu wakeups per second since the last call to @@ -2354,7 +2555,7 @@ declare namespace Electron { interface CrashReport { - // Docs: http://electron.atom.io/docs/api/structures/crash-report + // Docs: http://electronjs.org/docs/api/structures/crash-report date: Date; id: string; @@ -2362,7 +2563,7 @@ declare namespace Electron { interface CrashReporter extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/crash-reporter + // Docs: http://electronjs.org/docs/api/crash-reporter /** * Set an extra parameter to be sent with the crash report. The values specified @@ -2373,8 +2574,10 @@ declare namespace Electron { */ addExtraParameter(key: string, value: string): void; /** - * Returns the date and ID of the last crash report. If no crash reports have been - * sent or the crash reporter has not been started, null is returned. + * Returns the date and ID of the last crash report. Only crash reports that have + * been uploaded will be returned; even if a crash report is present on disk it + * will not be returned until it is uploaded. In the case that there are no + * uploaded reports, null is returned. */ getLastCrashReport(): CrashReport; /** @@ -2430,7 +2633,7 @@ declare namespace Electron { class Debugger extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/debugger + // Docs: http://electronjs.org/docs/api/debugger /** * Emitted when debugging session is terminated. This happens either when @@ -2516,7 +2719,7 @@ declare namespace Electron { interface DesktopCapturer extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/desktop-capturer + // Docs: http://electronjs.org/docs/api/desktop-capturer /** * Starts gathering information about all available desktop media sources, and @@ -2529,7 +2732,7 @@ declare namespace Electron { interface DesktopCapturerSource { - // Docs: http://electron.atom.io/docs/api/structures/desktop-capturer-source + // Docs: http://electronjs.org/docs/api/structures/desktop-capturer-source /** * A unique identifier that will correspond to the id of the matching returned by @@ -2545,8 +2748,8 @@ declare namespace Electron { */ id: string; /** - * A screen source will be named either Entire Screen or Screen , while the - * name of a window source will match the window title. + * A screen source will be named either Entire Screen or Screen , while the name of + * a window source will match the window title. */ name: string; /** @@ -2560,7 +2763,7 @@ declare namespace Electron { interface Dialog extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/dialog + // Docs: http://electronjs.org/docs/api/dialog /** * On macOS, this displays a modal dialog that shows a message and certificate @@ -2621,7 +2824,7 @@ declare namespace Electron { * file selector and a directory selector, so if you set properties to ['openFile', * 'openDirectory'] on these platforms, a directory selector will be shown. */ - showOpenDialog(browserWindow: BrowserWindow, options: OpenDialogOptions, callback?: (filePaths: string[], bookmarks: string[]) => void): string[]; + showOpenDialog(browserWindow: BrowserWindow, options: OpenDialogOptions, callback?: (filePaths: string[], bookmarks: string[]) => void): (string[]) | (undefined); /** * The browserWindow argument allows the dialog to attach itself to a parent * window, making it modal. The filters specifies an array of file types that can @@ -2634,7 +2837,7 @@ declare namespace Electron { * file selector and a directory selector, so if you set properties to ['openFile', * 'openDirectory'] on these platforms, a directory selector will be shown. */ - showOpenDialog(options: OpenDialogOptions, callback?: (filePaths: string[], bookmarks: string[]) => void): string[]; + showOpenDialog(options: OpenDialogOptions, callback?: (filePaths: string[], bookmarks: string[]) => void): (string[]) | (undefined); /** * The browserWindow argument allows the dialog to attach itself to a parent * window, making it modal. The filters specifies an array of file types that can @@ -2642,7 +2845,7 @@ declare namespace Electron { * the API call will be asynchronous and the result will be passed via * callback(filename). */ - showSaveDialog(browserWindow: BrowserWindow, options: SaveDialogOptions, callback?: (filename: string, bookmark: string) => void): string; + showSaveDialog(browserWindow: BrowserWindow, options: SaveDialogOptions, callback?: (filename: string, bookmark: string) => void): (string) | (undefined); /** * The browserWindow argument allows the dialog to attach itself to a parent * window, making it modal. The filters specifies an array of file types that can @@ -2650,12 +2853,12 @@ declare namespace Electron { * the API call will be asynchronous and the result will be passed via * callback(filename). */ - showSaveDialog(options: SaveDialogOptions, callback?: (filename: string, bookmark: string) => void): string; + showSaveDialog(options: SaveDialogOptions, callback?: (filename: string, bookmark: string) => void): (string) | (undefined); } interface Display { - // Docs: http://electron.atom.io/docs/api/structures/display + // Docs: http://electronjs.org/docs/api/structures/display bounds: Rectangle; /** @@ -2681,7 +2884,7 @@ declare namespace Electron { class DownloadItem extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/download-item + // Docs: http://electronjs.org/docs/api/download-item /** * Emitted when the download is in a terminal state. This includes a completed @@ -2784,7 +2987,7 @@ declare namespace Electron { interface FileFilter { - // Docs: http://electron.atom.io/docs/api/structures/file-filter + // Docs: http://electronjs.org/docs/api/structures/file-filter extensions: string[]; name: string; @@ -2792,7 +2995,7 @@ declare namespace Electron { interface GlobalShortcut extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/global-shortcut + // Docs: http://electronjs.org/docs/api/global-shortcut /** * When the accelerator is already taken by other applications, this call will @@ -2805,7 +3008,9 @@ declare namespace Electron { * registered shortcut is pressed by the user. When the accelerator is already * taken by other applications, this call will silently fail. This behavior is * intended by operating systems, since they don't want applications to fight for - * global shortcuts. + * global shortcuts. The following accelerators will not be registered successfully + * on macOS 10.14 Mojave unless the app has been authorized as a trusted + * accessibility client: */ register(accelerator: Accelerator, callback: Function): void; /** @@ -2820,65 +3025,65 @@ declare namespace Electron { interface GPUFeatureStatus { - // Docs: http://electron.atom.io/docs/api/structures/gpu-feature-status + // Docs: http://electronjs.org/docs/api/structures/gpu-feature-status /** - * Canvas + * Canvas. */ '2d_canvas': string; /** - * Flash + * Flash. */ flash_3d: string; /** - * Flash Stage3D + * Flash Stage3D. */ flash_stage3d: string; /** - * Flash Stage3D Baseline profile + * Flash Stage3D Baseline profile. */ flash_stage3d_baseline: string; /** - * Compositing + * Compositing. */ gpu_compositing: string; /** - * Multiple Raster Threads + * Multiple Raster Threads. */ multiple_raster_threads: string; /** - * Native GpuMemoryBuffers + * Native GpuMemoryBuffers. */ native_gpu_memory_buffers: string; /** - * Rasterization + * Rasterization. */ rasterization: string; /** - * Video Decode + * Video Decode. */ video_decode: string; /** - * Video Encode + * Video Encode. */ video_encode: string; /** - * VPx Video Decode + * VPx Video Decode. */ vpx_decode: string; /** - * WebGL + * WebGL. */ webgl: string; /** - * WebGL2 + * WebGL2. */ webgl2: string; } interface InAppPurchase extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/in-app-purchase + // Docs: http://electronjs.org/docs/api/in-app-purchase /** * Emitted when one or more transactions have been updated. @@ -2926,7 +3131,7 @@ declare namespace Electron { class IncomingMessage extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/incoming-message + // Docs: http://electronjs.org/docs/api/incoming-message /** * Emitted when a request has been canceled during an ongoing HTTP transaction. @@ -2987,7 +3192,7 @@ declare namespace Electron { interface IOCounters { - // Docs: http://electron.atom.io/docs/api/structures/io-counters + // Docs: http://electronjs.org/docs/api/structures/io-counters /** * Then number of I/O other operations. @@ -3017,7 +3222,7 @@ declare namespace Electron { interface IpcMain extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/ipc-main + // Docs: http://electronjs.org/docs/api/ipc-main /** * Listens to channel, when a new message arrives listener would be called with @@ -3042,7 +3247,7 @@ declare namespace Electron { interface IpcRenderer extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/ipc-renderer + // Docs: http://electronjs.org/docs/api/ipc-renderer /** * Listens to channel, when a new message arrives listener would be called with @@ -3092,7 +3297,7 @@ declare namespace Electron { interface JumpListCategory { - // Docs: http://electron.atom.io/docs/api/structures/jump-list-category + // Docs: http://electronjs.org/docs/api/structures/jump-list-category /** * Array of objects if type is tasks or custom, otherwise it should be omitted. @@ -3110,7 +3315,7 @@ declare namespace Electron { interface JumpListItem { - // Docs: http://electron.atom.io/docs/api/structures/jump-list-item + // Docs: http://electronjs.org/docs/api/structures/jump-list-item /** * The command line arguments when program is executed. Should only be set if type @@ -3155,38 +3360,9 @@ declare namespace Electron { type?: ('task' | 'separator' | 'file'); } - interface MemoryInfo { - - // Docs: http://electron.atom.io/docs/api/structures/memory-info - - /** - * The maximum amount of memory that has ever been pinned to actual physical RAM. - * On macOS its value will always be 0. - */ - peakWorkingSetSize: number; - /** - * Process id of the process. - */ - pid: number; - /** - * The amount of memory not shared by other processes, such as JS heap or HTML - * content. - */ - privateBytes: number; - /** - * The amount of memory shared between processes, typically memory consumed by the - * Electron code itself - */ - sharedBytes: number; - /** - * The amount of memory currently pinned to actual physical RAM. - */ - workingSetSize: number; - } - interface MemoryUsageDetails { - // Docs: http://electron.atom.io/docs/api/structures/memory-usage-details + // Docs: http://electronjs.org/docs/api/structures/memory-usage-details count: number; liveSize: number; @@ -3195,7 +3371,7 @@ declare namespace Electron { class Menu { - // Docs: http://electron.atom.io/docs/api/menu + // Docs: http://electronjs.org/docs/api/menu /** * Emitted when a popup is closed either manually or with menu.closePopup(). @@ -3222,7 +3398,7 @@ declare namespace Electron { * Note: The returned Menu instance doesn't support dynamic addition or removal of * menu items. Instance properties can still be dynamically modified. */ - static getApplicationMenu(): Menu | null; + static getApplicationMenu(): (Menu) | (null); /** * Sends the action to the first responder of application. This is used for * emulating default macOS menu behaviors. Usually you would use the role property @@ -3236,7 +3412,7 @@ declare namespace Electron { * Windows and Linux but has no effect on macOS. Note: This API has to be called * after the ready event of app module. */ - static setApplicationMenu(menu: Menu | null): void; + static setApplicationMenu(menu: (Menu) | (null)): void; /** * Appends the menuItem to the menu. */ @@ -3253,13 +3429,13 @@ declare namespace Electron { /** * Pops up this menu as a context menu in the BrowserWindow. */ - popup(options: PopupOptions): void; + popup(options?: PopupOptions): void; items: MenuItem[]; } class MenuItem { - // Docs: http://electron.atom.io/docs/api/menu-item + // Docs: http://electronjs.org/docs/api/menu-item constructor(options: MenuItemConstructorOptions); checked: boolean; @@ -3271,21 +3447,21 @@ declare namespace Electron { interface MimeTypedBuffer { - // Docs: http://electron.atom.io/docs/api/structures/mime-typed-buffer + // Docs: http://electronjs.org/docs/api/structures/mime-typed-buffer /** - * The actual Buffer content + * The actual Buffer content. */ data: Buffer; /** - * The mimeType of the Buffer that you are sending + * The mimeType of the Buffer that you are sending. */ mimeType: string; } class NativeImage { - // Docs: http://electron.atom.io/docs/api/native-image + // Docs: http://electronjs.org/docs/api/native-image /** * Creates an empty NativeImage instance. @@ -3303,7 +3479,14 @@ declare namespace Electron { * Creates a new NativeImage instance from the NSImage that maps to the given image * name. See NSImageName for a list of possible values. The hslShift is applied to * the image with the following rules This means that [-1, 0, 1] will make the - * image completely white and [-1, 1, 0] will make the image completely black. + * image completely white and [-1, 1, 0] will make the image completely black. In + * some cases, the NSImageName doesn't match its string representation; one example + * of this is NSFolderImageName, whose string representation would actually be + * NSFolder. Therefore, you'll need to determine the correct string representation + * for your image before passing it in. This can be done with the following: echo + * -e '#import \nint main() { NSLog(@"%@", SYSTEM_IMAGE_NAME); }' | + * clang -otest -x objective-c -framework Cocoa - && ./test where SYSTEM_IMAGE_NAME + * should be replaced with any value from this list. */ static createFromNamedImage(imageName: string, hslShift: number[]): NativeImage; /** @@ -3352,7 +3535,7 @@ declare namespace Electron { interface Net extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/net + // Docs: http://electronjs.org/docs/api/net /** * Creates a ClientRequest instance using the provided options which are directly @@ -3360,12 +3543,12 @@ declare namespace Electron { * to issue both secure and insecure HTTP requests according to the specified * protocol scheme in the options object. */ - request(options: any | string): ClientRequest; + request(options: (any) | (string)): ClientRequest; } interface NetLog extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/net-log + // Docs: http://electronjs.org/docs/api/net-log /** * Starts recording network events to path. @@ -3388,7 +3571,7 @@ declare namespace Electron { class Notification extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/notification + // Docs: http://electronjs.org/docs/api/notification on(event: 'action', listener: (event: Event, /** @@ -3478,7 +3661,7 @@ declare namespace Electron { interface NotificationAction { - // Docs: http://electron.atom.io/docs/api/structures/notification-action + // Docs: http://electronjs.org/docs/api/structures/notification-action /** * The label for the given action. @@ -3492,7 +3675,7 @@ declare namespace Electron { interface Point { - // Docs: http://electron.atom.io/docs/api/structures/point + // Docs: http://electronjs.org/docs/api/structures/point x: number; y: number; @@ -3500,7 +3683,7 @@ declare namespace Electron { interface PowerMonitor extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/power-monitor + // Docs: http://electronjs.org/docs/api/power-monitor /** * Emitted when the system is about to lock the screen. @@ -3554,11 +3737,22 @@ declare namespace Electron { once(event: 'unlock-screen', listener: Function): this; addListener(event: 'unlock-screen', listener: Function): this; removeListener(event: 'unlock-screen', listener: Function): this; + /** + * Calculate the system idle state. idleThreshold is the amount of time (in + * seconds) before considered idle. callback will be called synchronously on some + * systems and with an idleState argument that describes the system's state. locked + * is available on supported systems only. + */ + querySystemIdleState(idleThreshold: number, callback: (idleState: 'active' | 'idle' | 'locked' | 'unknown') => void): void; + /** + * Calculate system idle time in seconds. + */ + querySystemIdleTime(callback: (idleTime: number) => void): void; } interface PowerSaveBlocker extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/power-save-blocker + // Docs: http://electronjs.org/docs/api/power-save-blocker isStarted(id: number): boolean; /** @@ -3580,7 +3774,7 @@ declare namespace Electron { interface PrinterInfo { - // Docs: http://electron.atom.io/docs/api/structures/printer-info + // Docs: http://electronjs.org/docs/api/structures/printer-info description: string; isDefault: boolean; @@ -3590,16 +3784,12 @@ declare namespace Electron { interface ProcessMetric { - // Docs: http://electron.atom.io/docs/api/structures/process-metric + // Docs: http://electronjs.org/docs/api/structures/process-metric /** * CPU usage of the process. */ cpu: CPUUsage; - /** - * Memory information for the process. - */ - memory: MemoryInfo; /** * Process id of the process. */ @@ -3612,7 +3802,7 @@ declare namespace Electron { interface Product { - // Docs: http://electron.atom.io/docs/api/structures/product + // Docs: http://electronjs.org/docs/api/structures/product /** * The total size of the content, in bytes. @@ -3651,7 +3841,7 @@ declare namespace Electron { interface Protocol extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/protocol + // Docs: http://electronjs.org/docs/api/protocol /** * Intercepts scheme protocol and uses handler as the protocol's new handler which @@ -3672,7 +3862,7 @@ declare namespace Electron { * Same as protocol.registerStreamProtocol, except that it replaces an existing * protocol handler. */ - interceptStreamProtocol(scheme: string, handler: (request: InterceptStreamProtocolRequest, callback: (stream?: ReadableStream | StreamProtocolResponse) => void) => void, completion?: (error: Error) => void): void; + interceptStreamProtocol(scheme: string, handler: (request: InterceptStreamProtocolRequest, callback: (stream?: (NodeJS.ReadableStream) | (StreamProtocolResponse)) => void) => void, completion?: (error: Error) => void): void; /** * Intercepts scheme protocol and uses handler as the protocol's new handler which * sends a String as a response. @@ -3689,15 +3879,15 @@ declare namespace Electron { * with either a Buffer object or an object that has the data, mimeType, and * charset properties. Example: */ - registerBufferProtocol(scheme: string, handler: (request: RegisterBufferProtocolRequest, callback: (buffer?: Buffer | MimeTypedBuffer) => void) => void, completion?: (error: Error) => void): void; + registerBufferProtocol(scheme: string, handler: (request: RegisterBufferProtocolRequest, callback: (buffer?: (Buffer) | (MimeTypedBuffer)) => void) => void, completion?: (error: Error) => void): void; /** * Registers a protocol of scheme that will send the file as a response. The * handler will be called with handler(request, callback) when a request is going * to be created with scheme. completion will be called with completion(null) when * scheme is successfully registered or completion(error) when failed. To handle * the request, the callback should be called with either the file's path or an - * object that has a path property, e.g. callback(filePath) or callback({path: - * filePath}). When callback is called with nothing, a number, or an object that + * object that has a path property, e.g. callback(filePath) or callback({ path: + * filePath }). When callback is called with nothing, a number, or an object that * has an error property, the request will fail with the error number you * specified. For the available error numbers you can use, please see the net error * list. By default the scheme is treated like http:, which is parsed differently @@ -3741,7 +3931,7 @@ declare namespace Electron { * that implements the readable stream API (emits data/end/error events). For * example, here's how a file could be returned: */ - registerStreamProtocol(scheme: string, handler: (request: RegisterStreamProtocolRequest, callback: (stream?: ReadableStream | StreamProtocolResponse) => void) => void, completion?: (error: Error) => void): void; + registerStreamProtocol(scheme: string, handler: (request: RegisterStreamProtocolRequest, callback: (stream?: (NodeJS.ReadableStream) | (StreamProtocolResponse)) => void) => void, completion?: (error: Error) => void): void; /** * Registers a protocol of scheme that will send a String as a response. The usage * is the same with registerFileProtocol, except that the callback should be called @@ -3761,29 +3951,29 @@ declare namespace Electron { interface Rectangle { - // Docs: http://electron.atom.io/docs/api/structures/rectangle + // Docs: http://electronjs.org/docs/api/structures/rectangle /** - * The height of the rectangle (must be an integer) + * The height of the rectangle (must be an integer). */ height: number; /** - * The width of the rectangle (must be an integer) + * The width of the rectangle (must be an integer). */ width: number; /** - * The x coordinate of the origin of the rectangle (must be an integer) + * The x coordinate of the origin of the rectangle (must be an integer). */ x: number; /** - * The y coordinate of the origin of the rectangle (must be an integer) + * The y coordinate of the origin of the rectangle (must be an integer). */ y: number; } interface Referrer { - // Docs: http://electron.atom.io/docs/api/structures/referrer + // Docs: http://electronjs.org/docs/api/structures/referrer /** * Can be default, unsafe-url, no-referrer-when-downgrade, no-referrer, origin, @@ -3799,7 +3989,7 @@ declare namespace Electron { interface Remote extends MainInterface { - // Docs: http://electron.atom.io/docs/api/remote + // Docs: http://electronjs.org/docs/api/remote getCurrentWebContents(): WebContents; /** @@ -3822,7 +4012,7 @@ declare namespace Electron { interface RemoveClientCertificate { - // Docs: http://electron.atom.io/docs/api/structures/remove-client-certificate + // Docs: http://electronjs.org/docs/api/structures/remove-client-certificate /** * Origin of the server whose associated client certificate must be removed from @@ -3837,7 +4027,7 @@ declare namespace Electron { interface RemovePassword { - // Docs: http://electron.atom.io/docs/api/structures/remove-password + // Docs: http://electronjs.org/docs/api/structures/remove-password /** * When provided, the authentication info related to the origin will only be @@ -3869,7 +4059,7 @@ declare namespace Electron { interface Screen extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/screen + // Docs: http://electronjs.org/docs/api/screen /** * Emitted when newDisplay has been added. @@ -3920,7 +4110,7 @@ declare namespace Electron { * relative to the display nearest to window. If window is null, scaling will be * performed to the display nearest to rect. */ - dipToScreenRect(window: BrowserWindow | null, rect: Rectangle): Rectangle; + dipToScreenRect(window: (BrowserWindow) | (null), rect: Rectangle): Rectangle; getAllDisplays(): Display[]; /** * The current absolute position of the mouse pointer. @@ -3939,44 +4129,44 @@ declare namespace Electron { * relative to the display nearest to window. If window is null, scaling will be * performed to the display nearest to rect. */ - screenToDipRect(window: BrowserWindow | null, rect: Rectangle): Rectangle; + screenToDipRect(window: (BrowserWindow) | (null), rect: Rectangle): Rectangle; } interface ScrubberItem { - // Docs: http://electron.atom.io/docs/api/structures/scrubber-item + // Docs: http://electronjs.org/docs/api/structures/scrubber-item /** - * The image to appear in this item + * The image to appear in this item. */ icon?: NativeImage; /** - * The text to appear in this item + * The text to appear in this item. */ label?: string; } interface SegmentedControlSegment { - // Docs: http://electron.atom.io/docs/api/structures/segmented-control-segment + // Docs: http://electronjs.org/docs/api/structures/segmented-control-segment /** - * Whether this segment is selectable. Default: true + * Whether this segment is selectable. Default: true. */ enabled?: boolean; /** - * The image to appear in this segment + * The image to appear in this segment. */ icon?: NativeImage; /** - * The text to appear in this segment + * The text to appear in this segment. */ label?: string; } class Session extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/session + // Docs: http://electronjs.org/docs/api/session /** * If partition starts with persist:, the page will use a persistent session @@ -4016,7 +4206,7 @@ declare namespace Electron { /** * Clears the session’s HTTP authentication cache. */ - clearAuthCache(options: RemovePassword | RemoveClientCertificate, callback?: Function): void; + clearAuthCache(options: (RemovePassword) | (RemoveClientCertificate), callback?: Function): void; /** * Clears the session’s HTTP cache. */ @@ -4075,12 +4265,18 @@ declare namespace Electron { * Downloads under the respective app folder. */ setDownloadPath(path: string): void; + /** + * Sets the handler which can be used to respond to permission checks for the + * session. Returning true will allow the permission and false will reject it. To + * clear the handler, call setPermissionCheckHandler(null). + */ + setPermissionCheckHandler(handler: ((webContents: WebContents, permission: string, requestingOrigin: string, details: PermissionCheckHandlerDetails) => boolean) | (null)): void; /** * Sets the handler which can be used to respond to permission requests for the * session. Calling callback(true) will allow the permission and callback(false) * will reject it. To clear the handler, call setPermissionRequestHandler(null). */ - setPermissionRequestHandler(handler: (webContents: WebContents, permission: string, callback: (permissionGranted: boolean) => void, details: PermissionRequestHandlerDetails) => void | null): void; + setPermissionRequestHandler(handler: ((webContents: WebContents, permission: string, callback: (permissionGranted: boolean) => void, details: PermissionRequestHandlerDetails) => void) | (null)): void; /** * Adds scripts that will be executed on ALL web contents that are associated with * this session just before normal preload scripts run. @@ -4102,13 +4298,14 @@ declare namespace Electron { */ setUserAgent(userAgent: string, acceptLanguages?: string): void; cookies: Cookies; + netLog: NetLog; protocol: Protocol; webRequest: WebRequest; } interface Shell { - // Docs: http://electron.atom.io/docs/api/shell + // Docs: http://electronjs.org/docs/api/shell /** * Play the beep sound. @@ -4148,7 +4345,7 @@ declare namespace Electron { interface ShortcutDetails { - // Docs: http://electron.atom.io/docs/api/structures/shortcut-details + // Docs: http://electronjs.org/docs/api/structures/shortcut-details /** * The Application User Model ID. Default is empty. @@ -4184,7 +4381,7 @@ declare namespace Electron { interface Size { - // Docs: http://electron.atom.io/docs/api/structures/size + // Docs: http://electronjs.org/docs/api/structures/size height: number; width: number; @@ -4192,25 +4389,25 @@ declare namespace Electron { interface StreamProtocolResponse { - // Docs: http://electron.atom.io/docs/api/structures/stream-protocol-response + // Docs: http://electronjs.org/docs/api/structures/stream-protocol-response /** - * A Node.js readable stream representing the response body + * A Node.js readable stream representing the response body. */ - data: ReadableStream; + data: NodeJS.ReadableStream; /** - * An object containing the response headers + * An object containing the response headers. */ headers: Headers; /** - * The HTTP response code + * The HTTP response code. */ statusCode: number; } interface SystemPreferences extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/system-preferences + // Docs: http://electronjs.org/docs/api/system-preferences on(event: 'accent-color-changed', listener: (event: Event, /** @@ -4260,8 +4457,41 @@ declare namespace Electron { * used, `false` otherwise. */ invertedColorScheme: boolean) => void): this; + /** + * Important: In order to properly leverage this API, you must set the + * NSMicrophoneUsageDescription and NSCameraUsageDescription strings in your app's + * Info.plist file. The values for these keys will be used to populate the + * permission dialogs so that the user will be properly informed as to the purpose + * of the permission request. See Electron Application Distribution for more + * information about how to set these in the context of Electron. This user consent + * was not required until macOS 10.14 Mojave, so this method will always return + * true if your system is running 10.13 High Sierra or lower. + */ + askForMediaAccess(mediaType: 'microphone' | 'camera'): Promise; getAccentColor(): string; + /** + * Gets the macOS appearance setting that you have declared you want for your + * application, maps to NSApplication.appearance. You can use the + * setAppLevelAppearance API to set this value. + */ + getAppLevelAppearance(): ('dark' | 'light' | 'unknown'); getColor(color: '3d-dark-shadow' | '3d-face' | '3d-highlight' | '3d-light' | '3d-shadow' | 'active-border' | 'active-caption' | 'active-caption-gradient' | 'app-workspace' | 'button-text' | 'caption-text' | 'desktop' | 'disabled-text' | 'highlight' | 'highlight-text' | 'hotlight' | 'inactive-border' | 'inactive-caption' | 'inactive-caption-gradient' | 'inactive-caption-text' | 'info-background' | 'info-text' | 'menu' | 'menu-highlight' | 'menubar' | 'menu-text' | 'scrollbar' | 'window' | 'window-frame' | 'window-text'): string; + /** + * Gets the macOS appearance setting that is currently applied to your application, + * maps to NSApplication.effectiveAppearance Please note that until Electron is + * built targeting the 10.14 SDK, your application's effectiveAppearance will + * default to 'light' and won't inherit the OS preference. In the interim in order + * for your application to inherit the OS preference you must set the + * NSRequiresAquaSystemAppearance key in your apps Info.plist to false. If you are + * using electron-packager or electron-forge just set the enableDarwinDarkMode + * packager option to true. See the Electron Packager API for more details. + */ + getEffectiveAppearance(): ('dark' | 'light' | 'unknown'); + /** + * This user consent was not required until macOS 10.14 Mojave, so this method will + * always return granted if your system is running 10.13 High Sierra or lower. + */ + getMediaAccessStatus(mediaType: string): ('not-determined' | 'granted' | 'denied' | 'restricted' | 'unknown'); /** * Some popular key and types are: */ @@ -4274,6 +4504,7 @@ declare namespace Electron { isDarkMode(): boolean; isInvertedColorScheme(): boolean; isSwipeTrackingFromScrollEventsEnabled(): boolean; + isTrustedAccessibilityClient(prompt: boolean): boolean; /** * Posts event as native notifications of macOS. The userInfo is an Object that * contains the user information dictionary sent along with the notification. @@ -4298,6 +4529,11 @@ declare namespace Electron { * global value of a key previously set with setUserDefault. */ removeUserDefault(key: string): void; + /** + * Sets the appearance setting for your application, this should override the + * system default and override the value of getEffectiveAppearance. + */ + setAppLevelAppearance(appearance: 'dark' | 'light'): void; /** * Set the value of key in NSUserDefaults. Note that type should match actual type * of value. An exception is thrown if they don't. Some popular key and types are: @@ -4341,7 +4577,7 @@ declare namespace Electron { interface Task { - // Docs: http://electron.atom.io/docs/api/structures/task + // Docs: http://electronjs.org/docs/api/structures/task /** * The command line arguments when program is executed. @@ -4376,7 +4612,7 @@ declare namespace Electron { interface ThumbarButton { - // Docs: http://electron.atom.io/docs/api/structures/thumbar-button + // Docs: http://electronjs.org/docs/api/structures/thumbar-button click: Function; /** @@ -4396,7 +4632,7 @@ declare namespace Electron { class TouchBarButton extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/touch-bar-button + // Docs: http://electronjs.org/docs/api/touch-bar-button constructor(options: TouchBarButtonConstructorOptions); backgroundColor: string; @@ -4406,7 +4642,7 @@ declare namespace Electron { class TouchBarColorPicker extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/touch-bar-color-picker + // Docs: http://electronjs.org/docs/api/touch-bar-color-picker constructor(options: TouchBarColorPickerConstructorOptions); availableColors: string[]; @@ -4415,14 +4651,14 @@ declare namespace Electron { class TouchBarGroup extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/touch-bar-group + // Docs: http://electronjs.org/docs/api/touch-bar-group constructor(options: TouchBarGroupConstructorOptions); } class TouchBarLabel extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/touch-bar-label + // Docs: http://electronjs.org/docs/api/touch-bar-label constructor(options: TouchBarLabelConstructorOptions); label: string; @@ -4431,7 +4667,7 @@ declare namespace Electron { class TouchBarPopover extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/touch-bar-popover + // Docs: http://electronjs.org/docs/api/touch-bar-popover constructor(options: TouchBarPopoverConstructorOptions); icon: NativeImage; @@ -4440,7 +4676,7 @@ declare namespace Electron { class TouchBarScrubber extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/touch-bar-scrubber + // Docs: http://electronjs.org/docs/api/touch-bar-scrubber constructor(options: TouchBarScrubberConstructorOptions); continuous: boolean; @@ -4453,7 +4689,7 @@ declare namespace Electron { class TouchBarSegmentedControl extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/touch-bar-segmented-control + // Docs: http://electronjs.org/docs/api/touch-bar-segmented-control constructor(options: TouchBarSegmentedControlConstructorOptions); segments: SegmentedControlSegment[]; @@ -4463,7 +4699,7 @@ declare namespace Electron { class TouchBarSlider extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/touch-bar-slider + // Docs: http://electronjs.org/docs/api/touch-bar-slider constructor(options: TouchBarSliderConstructorOptions); label: string; @@ -4474,14 +4710,14 @@ declare namespace Electron { class TouchBarSpacer extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/touch-bar-spacer + // Docs: http://electronjs.org/docs/api/touch-bar-spacer constructor(options: TouchBarSpacerConstructorOptions); } class TouchBar extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/touch-bar + // Docs: http://electronjs.org/docs/api/touch-bar constructor(options: TouchBarConstructorOptions); escapeItem: (TouchBarButton | TouchBarColorPicker | TouchBarGroup | TouchBarLabel | TouchBarPopover | TouchBarScrubber | TouchBarSegmentedControl | TouchBarSlider | TouchBarSpacer | null); @@ -4496,9 +4732,45 @@ declare namespace Electron { static TouchBarSpacer: typeof TouchBarSpacer; } + interface TraceCategoriesAndOptions { + + // Docs: http://electronjs.org/docs/api/structures/trace-categories-and-options + + /** + * – is a filter to control what category groups should be traced. A filter can + * have an optional prefix to exclude category groups that contain a matching + * category. Having both included and excluded category patterns in the same list + * is not supported. Examples: test_MyTest*, test_MyTest*,test_OtherStuff, + * -excluded_category1,-excluded_category2. + */ + categoryFilter: string; + /** + * Controls what kind of tracing is enabled, it is a comma-delimited sequence of + * the following strings: record-until-full, record-continuously, trace-to-console, + * enable-sampling, enable-systrace, e.g. 'record-until-full,enable-sampling'. The + * first 3 options are trace recording modes and hence mutually exclusive. If more + * than one trace recording modes appear in the traceOptions string, the last one + * takes precedence. If none of the trace recording modes are specified, recording + * mode is record-until-full. The trace option will first be reset to the default + * option (record_mode set to record-until-full, enable_sampling and + * enable_systrace set to false) before options parsed from traceOptions are + * applied on it. + */ + traceOptions: string; + } + + interface TraceConfig { + + // Docs: http://electronjs.org/docs/api/structures/trace-config + + excluded_categories?: string[]; + included_categories?: string[]; + memory_dump_config?: MemoryDumpConfig; + } + interface Transaction { - // Docs: http://electron.atom.io/docs/api/structures/transaction + // Docs: http://electronjs.org/docs/api/structures/transaction /** * The error code if an error occurred while processing the transaction. @@ -4530,7 +4802,7 @@ declare namespace Electron { class Tray extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/tray + // Docs: http://electronjs.org/docs/api/tray /** * Emitted when the tray balloon is clicked. @@ -4782,7 +5054,7 @@ declare namespace Electron { * The bounds of tray icon. */ bounds: Rectangle) => void): this; - constructor(image: NativeImage | string); + constructor(image: (NativeImage) | (string)); /** * Destroys the tray icon immediately. */ @@ -4806,7 +5078,7 @@ declare namespace Electron { /** * Sets the context menu for this icon. */ - setContextMenu(menu: Menu | null): void; + setContextMenu(menu: (Menu) | (null)): void; /** * Sets when the tray's icon background becomes highlighted (in blue). Note: You * can use highlightMode with a BrowserWindow by toggling between 'never' and @@ -4822,11 +5094,11 @@ declare namespace Electron { /** * Sets the image associated with this tray icon. */ - setImage(image: NativeImage | string): void; + setImage(image: (NativeImage) | (string)): void; /** * Sets the image associated with this tray icon when pressed on macOS. */ - setPressedImage(image: NativeImage | string): void; + setPressedImage(image: (NativeImage) | (string)): void; /** * Sets the title displayed aside of the tray icon in the status bar (Support ANSI * colors). @@ -4840,7 +5112,7 @@ declare namespace Electron { interface UploadBlob { - // Docs: http://electron.atom.io/docs/api/structures/upload-blob + // Docs: http://electronjs.org/docs/api/structures/upload-blob /** * UUID of blob data to upload. @@ -4854,7 +5126,7 @@ declare namespace Electron { interface UploadData { - // Docs: http://electron.atom.io/docs/api/structures/upload-data + // Docs: http://electronjs.org/docs/api/structures/upload-data /** * UUID of blob data. Use method to retrieve the data. @@ -4872,7 +5144,7 @@ declare namespace Electron { interface UploadFile { - // Docs: http://electron.atom.io/docs/api/structures/upload-file + // Docs: http://electronjs.org/docs/api/structures/upload-file /** * Path of file to be uploaded. @@ -4898,7 +5170,7 @@ declare namespace Electron { interface UploadRawData { - // Docs: http://electron.atom.io/docs/api/structures/upload-raw-data + // Docs: http://electronjs.org/docs/api/structures/upload-raw-data /** * Data to be uploaded. @@ -4912,7 +5184,7 @@ declare namespace Electron { class WebContents extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/web-contents + // Docs: http://electronjs.org/docs/api/web-contents static fromId(id: number): WebContents; static getAllWebContents(): WebContents[]; @@ -5136,22 +5408,22 @@ declare namespace Electron { */ on(event: 'did-attach-webview', listener: (event: Event, /** - * The guest web contents that is used by the ``. + * The guest web contents that is used by the ` */ webContents: WebContents) => void): this; once(event: 'did-attach-webview', listener: (event: Event, /** - * The guest web contents that is used by the ``. + * The guest web contents that is used by the ` */ webContents: WebContents) => void): this; addListener(event: 'did-attach-webview', listener: (event: Event, /** - * The guest web contents that is used by the ``. + * The guest web contents that is used by the ` */ webContents: WebContents) => void): this; removeListener(event: 'did-attach-webview', listener: (event: Event, /** - * The guest web contents that is used by the ``. + * The guest web contents that is used by the ` */ webContents: WebContents) => void): this; /** @@ -5162,22 +5434,22 @@ declare namespace Electron { /** * Theme color is in format of '#rrggbb'. It is `null` when no theme color is set. */ - color: string | null) => void): this; + color: (string) | (null)) => void): this; once(event: 'did-change-theme-color', listener: (event: Event, /** * Theme color is in format of '#rrggbb'. It is `null` when no theme color is set. */ - color: string | null) => void): this; + color: (string) | (null)) => void): this; addListener(event: 'did-change-theme-color', listener: (event: Event, /** * Theme color is in format of '#rrggbb'. It is `null` when no theme color is set. */ - color: string | null) => void): this; + color: (string) | (null)) => void): this; removeListener(event: 'did-change-theme-color', listener: (event: Event, /** * Theme color is in format of '#rrggbb'. It is `null` when no theme color is set. */ - color: string | null) => void): this; + color: (string) | (null)) => void): this; /** * This event is like did-finish-load but emitted when the load failed or was * cancelled, e.g. window.stop() is invoked. The full list of error codes and their @@ -5366,6 +5638,35 @@ declare namespace Electron { isMainFrame: boolean, frameProcessId: number, frameRoutingId: number) => void): this; + /** + * Emitted after a server side redirect occurs during navigation. For example a + * 302 redirect. This event can not be prevented, if you want to prevent redirects + * you should checkout out the will-redirect event above. + */ + on(event: 'did-redirect-navigation', listener: (event: Event, + url: string, + isInPlace: boolean, + isMainFrame: boolean, + frameProcessId: number, + frameRoutingId: number) => void): this; + once(event: 'did-redirect-navigation', listener: (event: Event, + url: string, + isInPlace: boolean, + isMainFrame: boolean, + frameProcessId: number, + frameRoutingId: number) => void): this; + addListener(event: 'did-redirect-navigation', listener: (event: Event, + url: string, + isInPlace: boolean, + isMainFrame: boolean, + frameProcessId: number, + frameRoutingId: number) => void): this; + removeListener(event: 'did-redirect-navigation', listener: (event: Event, + url: string, + isInPlace: boolean, + isMainFrame: boolean, + frameProcessId: number, + frameRoutingId: number) => void): this; /** * Corresponds to the points in time when the spinner of the tab started spinning. */ @@ -5377,22 +5678,26 @@ declare namespace Electron { * Emitted when any frame (including main) starts navigating. isInplace will be * true for in-page navigations. */ - on(event: 'did-start-navigation', listener: (url: string, + on(event: 'did-start-navigation', listener: (event: Event, + url: string, isInPlace: boolean, isMainFrame: boolean, frameProcessId: number, frameRoutingId: number) => void): this; - once(event: 'did-start-navigation', listener: (url: string, + once(event: 'did-start-navigation', listener: (event: Event, + url: string, isInPlace: boolean, isMainFrame: boolean, frameProcessId: number, frameRoutingId: number) => void): this; - addListener(event: 'did-start-navigation', listener: (url: string, + addListener(event: 'did-start-navigation', listener: (event: Event, + url: string, isInPlace: boolean, isMainFrame: boolean, frameProcessId: number, frameRoutingId: number) => void): this; - removeListener(event: 'did-start-navigation', listener: (url: string, + removeListener(event: 'did-start-navigation', listener: (event: Event, + url: string, isInPlace: boolean, isMainFrame: boolean, frameProcessId: number, @@ -5577,6 +5882,22 @@ declare namespace Electron { * Array of URLs. */ favicons: string[]) => void): this; + /** + * Fired when page title is set during navigation. explicitSet is false when title + * is synthesized from file url. + */ + on(event: 'page-title-updated', listener: (event: Event, + title: string, + explicitSet: boolean) => void): this; + once(event: 'page-title-updated', listener: (event: Event, + title: string, + explicitSet: boolean) => void): this; + addListener(event: 'page-title-updated', listener: (event: Event, + title: string, + explicitSet: boolean) => void): this; + removeListener(event: 'page-title-updated', listener: (event: Event, + title: string, + explicitSet: boolean) => void): this; /** * Emitted when a new frame is generated. Only the dirty area is passed in the * buffer. @@ -5620,6 +5941,76 @@ declare namespace Electron { removeListener(event: 'plugin-crashed', listener: (event: Event, name: string, version: string) => void): this; + /** + * Emitted when remote.getBuiltin() is called in the renderer process. Calling + * event.preventDefault() will prevent the module from being returned. Custom value + * can be returned by setting event.returnValue. + */ + on(event: 'remote-get-builtin', listener: (event: Event, + moduleName: string) => void): this; + once(event: 'remote-get-builtin', listener: (event: Event, + moduleName: string) => void): this; + addListener(event: 'remote-get-builtin', listener: (event: Event, + moduleName: string) => void): this; + removeListener(event: 'remote-get-builtin', listener: (event: Event, + moduleName: string) => void): this; + /** + * Emitted when remote.getCurrentWebContents() is called in the renderer process. + * Calling event.preventDefault() will prevent the object from being returned. + * Custom value can be returned by setting event.returnValue. + */ + on(event: 'remote-get-current-web-contents', listener: (event: Event) => void): this; + once(event: 'remote-get-current-web-contents', listener: (event: Event) => void): this; + addListener(event: 'remote-get-current-web-contents', listener: (event: Event) => void): this; + removeListener(event: 'remote-get-current-web-contents', listener: (event: Event) => void): this; + /** + * Emitted when remote.getCurrentWindow() is called in the renderer process. + * Calling event.preventDefault() will prevent the object from being returned. + * Custom value can be returned by setting event.returnValue. + */ + on(event: 'remote-get-current-window', listener: (event: Event) => void): this; + once(event: 'remote-get-current-window', listener: (event: Event) => void): this; + addListener(event: 'remote-get-current-window', listener: (event: Event) => void): this; + removeListener(event: 'remote-get-current-window', listener: (event: Event) => void): this; + /** + * Emitted when remote.getGlobal() is called in the renderer process. Calling + * event.preventDefault() will prevent the global from being returned. Custom value + * can be returned by setting event.returnValue. + */ + on(event: 'remote-get-global', listener: (event: Event, + globalName: string) => void): this; + once(event: 'remote-get-global', listener: (event: Event, + globalName: string) => void): this; + addListener(event: 'remote-get-global', listener: (event: Event, + globalName: string) => void): this; + removeListener(event: 'remote-get-global', listener: (event: Event, + globalName: string) => void): this; + /** + * Emitted when .getWebContents() is called in the renderer process. + * Calling event.preventDefault() will prevent the object from being returned. + * Custom value can be returned by setting event.returnValue. + */ + on(event: 'remote-get-guest-web-contents', listener: (event: Event, + guestWebContents: WebContents) => void): this; + once(event: 'remote-get-guest-web-contents', listener: (event: Event, + guestWebContents: WebContents) => void): this; + addListener(event: 'remote-get-guest-web-contents', listener: (event: Event, + guestWebContents: WebContents) => void): this; + removeListener(event: 'remote-get-guest-web-contents', listener: (event: Event, + guestWebContents: WebContents) => void): this; + /** + * Emitted when remote.require() is called in the renderer process. Calling + * event.preventDefault() will prevent the module from being returned. Custom value + * can be returned by setting event.returnValue. + */ + on(event: 'remote-require', listener: (event: Event, + moduleName: string) => void): this; + once(event: 'remote-require', listener: (event: Event, + moduleName: string) => void): this; + addListener(event: 'remote-require', listener: (event: Event, + moduleName: string) => void): this; + removeListener(event: 'remote-require', listener: (event: Event, + moduleName: string) => void): this; /** * Emitted when the unresponsive web page becomes responsive again. */ @@ -5699,8 +6090,7 @@ declare namespace Electron { */ webPreferences: any, /** - * The other `` parameters such as the `src` URL. This object can be - * modified to adjust the parameters of the guest page. + * The other ` */ params: any) => void): this; once(event: 'will-attach-webview', listener: (event: Event, @@ -5710,8 +6100,7 @@ declare namespace Electron { */ webPreferences: any, /** - * The other `` parameters such as the `src` URL. This object can be - * modified to adjust the parameters of the guest page. + * The other ` */ params: any) => void): this; addListener(event: 'will-attach-webview', listener: (event: Event, @@ -5721,8 +6110,7 @@ declare namespace Electron { */ webPreferences: any, /** - * The other `` parameters such as the `src` URL. This object can be - * modified to adjust the parameters of the guest page. + * The other ` */ params: any) => void): this; removeListener(event: 'will-attach-webview', listener: (event: Event, @@ -5732,8 +6120,7 @@ declare namespace Electron { */ webPreferences: any, /** - * The other `` parameters such as the `src` URL. This object can be - * modified to adjust the parameters of the guest page. + * The other ` */ params: any) => void): this; /** @@ -5762,6 +6149,36 @@ declare namespace Electron { once(event: 'will-prevent-unload', listener: (event: Event) => void): this; addListener(event: 'will-prevent-unload', listener: (event: Event) => void): this; removeListener(event: 'will-prevent-unload', listener: (event: Event) => void): this; + /** + * Emitted as a server side redirect occurs during navigation. For example a 302 + * redirect. This event will be emitted after did-start-navigation and always + * before the did-redirect-navigation event for the same navigation. Calling + * event.preventDefault() will prevent the navigation (not just the redirect). + */ + on(event: 'will-redirect', listener: (event: Event, + url: string, + isInPlace: boolean, + isMainFrame: boolean, + frameProcessId: number, + frameRoutingId: number) => void): this; + once(event: 'will-redirect', listener: (event: Event, + url: string, + isInPlace: boolean, + isMainFrame: boolean, + frameProcessId: number, + frameRoutingId: number) => void): this; + addListener(event: 'will-redirect', listener: (event: Event, + url: string, + isInPlace: boolean, + isMainFrame: boolean, + frameProcessId: number, + frameRoutingId: number) => void): this; + removeListener(event: 'will-redirect', listener: (event: Event, + url: string, + isInPlace: boolean, + isMainFrame: boolean, + frameProcessId: number, + frameRoutingId: number) => void): this; /** * Adds the specified path to DevTools workspace. Must be used after DevTools * creation: @@ -5867,6 +6284,7 @@ declare namespace Electron { getPrinters(): PrinterInfo[]; getProcessId(): number; getTitle(): string; + getType(): ('backgroundPage' | 'window' | 'browserView' | 'remote' | 'webview' | 'offscreen'); getURL(): string; getUserAgent(): string; getWebRTCIPHandlingPolicy(): string; @@ -5925,6 +6343,7 @@ declare namespace Electron { invalidate(): void; isAudioMuted(): boolean; isCrashed(): boolean; + isCurrentlyAudible(): boolean; isDestroyed(): boolean; isDevToolsFocused(): boolean; isDevToolsOpened(): boolean; @@ -5939,7 +6358,7 @@ declare namespace Electron { * relative to the root of your application. For instance an app structure like * this: Would require code like this */ - loadFile(filePath: string): void; + loadFile(filePath: string, options?: LoadFileOptions): void; /** * Loads the url in the window. The url must contain the protocol prefix, e.g. the * http:// or file://. If the load should bypass http cache then use the pragma @@ -5964,8 +6383,8 @@ declare namespace Electron { * Prints window's web page. When silent is set to true, Electron will pick the * system's default printer if deviceName is empty and the default settings for * printing. Calling window.print() in web page is equivalent to calling - * webContents.print({silent: false, printBackground: false, deviceName: ''}). Use - * page-break-before: always; CSS style to force to print to a new page. + * webContents.print({ silent: false, printBackground: false, deviceName: '' }). + * Use page-break-before: always; CSS style to force to print to a new page. */ print(options?: PrintOptions, callback?: (success: boolean) => void): void; /** @@ -6026,6 +6445,11 @@ declare namespace Electron { * Mute the audio on the current web page. */ setAudioMuted(muted: boolean): void; + /** + * Controls whether or not this WebContents will throttle animations and timers + * when the page becomes backgrounded. This also affects the Page Visibility API. + */ + setBackgroundThrottling(allowed: boolean): void; /** * Uses the devToolsWebContents as the target WebContents to show devtools. The * devToolsWebContents must not have done any navigation, and it should not be used @@ -6103,6 +6527,10 @@ declare namespace Electron { * If offscreen rendering is enabled and painting, stop painting. */ stopPainting(): void; + /** + * Takes a V8 heap snapshot and saves it to filePath. + */ + takeHeapSnapshot(filePath: string): Promise; /** * Toggles the developer tools. */ @@ -6130,7 +6558,7 @@ declare namespace Electron { interface WebFrame extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/web-frame + // Docs: http://electronjs.org/docs/api/web-frame /** * Attempts to free memory that is no longer being used (like images from a @@ -6148,7 +6576,7 @@ declare namespace Electron { */ executeJavaScript(code: string, userGesture?: boolean, callback?: (result: any) => void): Promise; /** - * Work like executeJavaScript but evaluates scripts in isolated context. + * Work like executeJavaScript but evaluates scripts in an isolated context. */ executeJavaScriptInIsolatedWorld(worldId: number, scripts: WebSource[], userGesture?: boolean, callback?: (result: any) => void): void; findFrameByName(name: string): WebFrame; @@ -6251,7 +6679,7 @@ declare namespace Electron { class WebRequest extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/web-request + // Docs: http://electronjs.org/docs/api/web-request /** * The listener will be called with listener(details) when a server initiated @@ -6281,14 +6709,14 @@ declare namespace Electron { * connection is made to the server, but before any http data is sent. The callback * has to be called with an response object. */ - onBeforeSendHeaders(filter: OnBeforeSendHeadersFilter, listener: Function): void; + onBeforeSendHeaders(filter: OnBeforeSendHeadersFilter, listener: (details: OnBeforeSendHeadersDetails, callback: (response: OnBeforeSendHeadersResponse) => void) => void): void; /** * The listener will be called with listener(details, callback) before sending an * HTTP request, once the request headers are available. This may occur after a TCP * connection is made to the server, but before any http data is sent. The callback * has to be called with an response object. */ - onBeforeSendHeaders(listener: Function): void; + onBeforeSendHeaders(listener: (details: OnBeforeSendHeadersDetails, callback: (response: OnBeforeSendHeadersResponse) => void) => void): void; /** * The listener will be called with listener(details) when a request is completed. */ @@ -6310,13 +6738,13 @@ declare namespace Electron { * headers of a request have been received. The callback has to be called with an * response object. */ - onHeadersReceived(filter: OnHeadersReceivedFilter, listener: Function): void; + onHeadersReceived(filter: OnHeadersReceivedFilter, listener: (details: OnHeadersReceivedDetails, callback: (response: OnHeadersReceivedResponse) => void) => void): void; /** * The listener will be called with listener(details, callback) when HTTP response * headers of a request have been received. The callback has to be called with an * response object. */ - onHeadersReceived(listener: Function): void; + onHeadersReceived(listener: (details: OnHeadersReceivedDetails, callback: (response: OnHeadersReceivedResponse) => void) => void): void; /** * The listener will be called with listener(details) when first byte of the * response body is received. For HTTP requests, this means that the status line @@ -6345,7 +6773,7 @@ declare namespace Electron { interface WebSource { - // Docs: http://electron.atom.io/docs/api/structures/web-source + // Docs: http://electronjs.org/docs/api/structures/web-source code: string; /** @@ -6357,7 +6785,7 @@ declare namespace Electron { interface WebviewTag extends HTMLElement { - // Docs: http://electron.atom.io/docs/api/webview-tag + // Docs: http://electronjs.org/docs/api/webview-tag /** * Fired when a load has committed. This includes navigation within the current @@ -6481,11 +6909,6 @@ declare namespace Electron { */ addEventListener(event: 'crashed', listener: (event: Event) => void, useCapture?: boolean): this; removeEventListener(event: 'crashed', listener: (event: Event) => void): this; - /** - * Fired when the gpu process is crashed. - */ - addEventListener(event: 'gpu-crashed', listener: (event: Event) => void, useCapture?: boolean): this; - removeEventListener(event: 'gpu-crashed', listener: (event: Event) => void): this; /** * Fired when a plugin process is crashed. */ @@ -6569,6 +6992,10 @@ declare namespace Electron { * Executes editing command delete in page. */ delete(): void; + /** + * Initiates a download of the resource at url without navigating. + */ + downloadURL(url: string): void; /** * Evaluates code in page. If userGesture is set, it will create the user gesture * context in the page. HTML APIs like requestFullScreen, which require user @@ -6583,7 +7010,21 @@ declare namespace Electron { getTitle(): string; getURL(): string; getUserAgent(): string; + /** + * It depends on the remote module, it is therefore not available when this module + * is disabled. + */ getWebContents(): WebContents; + /** + * Sends a request to get current zoom factor, the callback will be called with + * callback(zoomFactor). + */ + getZoomFactor(callback: (zoomFactor: number) => void): void; + /** + * Sends a request to get current zoom level, the callback will be called with + * callback(zoomLevel). + */ + getZoomLevel(callback: (zoomLevel: number) => void): void; /** * Makes the guest page go back. */ @@ -6618,9 +7059,11 @@ declare namespace Electron { inspectServiceWorker(): void; isAudioMuted(): boolean; isCrashed(): boolean; + isCurrentlyAudible(): boolean; isDevToolsFocused(): boolean; isDevToolsOpened(): boolean; isLoading(): boolean; + isLoadingMainFrame(): boolean; isWaitingForResponse(): boolean; /** * Loads the url in the webview, the url must contain the protocol prefix, e.g. the @@ -6688,10 +7131,18 @@ declare namespace Electron { * Set guest page muted. */ setAudioMuted(muted: boolean): void; + /** + * Sets the maximum and minimum layout-based (i.e. non-visual) zoom level. + */ + setLayoutZoomLevelLimits(minimumLevel: number, maximumLevel: number): void; /** * Overrides the user agent for the guest page. */ setUserAgent(userAgent: string): void; + /** + * Sets the maximum and minimum pinch-to-zoom level. + */ + setVisualZoomLevelLimits(minimumLevel: number, maximumLevel: number): void; /** * Changes the zoom factor to the specified factor. Zoom factor is zoom percent * divided by 100, so 300% = 3.0. @@ -6700,7 +7151,8 @@ declare namespace Electron { /** * Changes the zoom level to the specified level. The original size is 0 and each * increment above or below represents zooming 20% larger or smaller to default - * limits of 300% and 50% of original size, respectively. + * limits of 300% and 50% of original size, respectively. The formula for this is + * scale := 1.2 ^ level. */ setZoomLevel(level: number): void; /** @@ -6753,6 +7205,11 @@ declare namespace Electron { * RuntimeEnabledFeatures.json5 file. */ enableblinkfeatures?: string; + /** + * When this attribute is false the guest page in webview will not have access to + * the remote module. The remote module is avaiable by default. + */ + enableremotemodule?: string; /** * Sets the referrer URL for the guest page. */ @@ -7026,7 +7483,7 @@ declare namespace Electron { * visual effects, you can also leave it undefined so the executable's icon will be * used. */ - icon?: NativeImage | string; + icon?: (NativeImage) | (string); /** * Whether window should be shown when created. Default is true. */ @@ -7063,9 +7520,8 @@ declare namespace Electron { enableLargerThanScreen?: boolean; /** * Window's background color as a hexadecimal value, like #66CD00 or #FFF or - * #80FFFFFF (alpha is supported). Default is #FFF (white). If transparent is set - * to true, only values with transparent (#00-------) or opaque (#FF-----) alpha - * values are respected. + * #80FFFFFF (alpha is supported if transparent is set to true). Default is #FFF + * (white). */ backgroundColor?: string; /** @@ -7292,7 +7748,7 @@ declare namespace Electron { } interface CrashReporterStartOptions { - companyName?: string; + companyName: string; /** * URL that crash reports will be sent to as POST. */ @@ -7394,7 +7850,8 @@ declare namespace Electron { */ value?: string; /** - * The domain of the cookie. Empty by default if omitted. + * The domain of the cookie; this will be normalized with a preceding dot so that + * it's also valid for subdomains. Empty by default if omitted. */ domain?: string; /** @@ -7448,7 +7905,7 @@ declare namespace Electron { /** * - */ - icon?: NativeImage | string; + icon?: (NativeImage) | (string); title: string; content: string; } @@ -7490,7 +7947,7 @@ declare namespace Electron { /** * Sets the image associated with this dock icon. */ - setIcon: (image: NativeImage | string) => void; + setIcon: (image: (NativeImage) | (string)) => void; } interface EnableNetworkEmulationOptions { @@ -7688,6 +8145,7 @@ declare namespace Electron { interface InterceptHttpProtocolRequest { url: string; + headers: Headers; referrer: string; method: string; uploadData: UploadData[]; @@ -7744,11 +8202,26 @@ declare namespace Electron { isMainFrame: boolean; } + interface LoadFileOptions { + /** + * Passed to url.format(). + */ + query?: Query; + /** + * Passed to url.format(). + */ + search?: string; + /** + * Passed to url.format(). + */ + hash?: string; + } + interface LoadURLOptions { /** * An HTTP Referrer url. */ - httpReferrer?: string | Referrer; + httpReferrer?: (string) | (Referrer); /** * A user agent originating the request. */ @@ -7757,7 +8230,7 @@ declare namespace Electron { * Extra headers separated by "\n" */ extraHeaders?: string; - postData?: UploadRawData[] | UploadFile[] | UploadBlob[]; + postData?: (UploadRawData[]) | (UploadFile[]) | (UploadBlob[]); /** * Base url (with trailing path separator) for files to be loaded by the data url. * This is needed only if the specified url is a data url and needs to load other @@ -7807,6 +8280,9 @@ declare namespace Electron { args?: string[]; } + interface MemoryDumpConfig { + } + interface MenuItemConstructorOptions { /** * Will be called with click(menuItem, browserWindow, event) when the menu item is @@ -7825,7 +8301,7 @@ declare namespace Electron { label?: string; sublabel?: string; accelerator?: Accelerator; - icon?: NativeImage | string; + icon?: (NativeImage) | (string); /** * If false, the menu item will be greyed out and unclickable. */ @@ -7838,22 +8314,46 @@ declare namespace Electron { * Should only be specified for checkbox or radio type menu items. */ checked?: boolean; + /** + * If false, the accelerator won't be registered with the system, but it will still + * be displayed. Defaults to true. + */ + registerAccelerator?: boolean; /** * Should be specified for submenu type menu items. If submenu is specified, the * type: 'submenu' can be omitted. If the value is not a then it will be * automatically converted to one using Menu.buildFromTemplate. */ - submenu?: MenuItemConstructorOptions[] | Menu; + submenu?: (MenuItemConstructorOptions[]) | (Menu); /** * Unique within a single menu. If defined then it can be used as a reference to * this item by the position attribute. */ id?: string; /** - * This field allows fine-grained definition of the specific location within a - * given menu. + * Inserts this item before the item with the specified label. If the referenced + * item doesn't exist the item will be inserted at the end of the menu. Also + * implies that the menu item in question should be placed in the same “group” as + * the item. */ - position?: string; + before?: string[]; + /** + * Inserts this item after the item with the specified label. If the referenced + * item doesn't exist the item will be inserted at the end of the menu. + */ + after?: string[]; + /** + * Provides a means for a single context menu to declare the placement of their + * containing group before the containing group of the item with the specified + * label. + */ + beforeGroupContaining?: string[]; + /** + * Provides a means for a single context menu to declare the placement of their + * containing group after the containing group of the item with the specified + * label. + */ + afterGroupContaining?: string[]; } interface MessageBoxOptions { @@ -7899,7 +8399,7 @@ declare namespace Electron { * The index of the button to be used to cancel the dialog, via the Esc key. By * default this is assigned to the first button with "cancel" or "no" as the label. * If no such labeled buttons exist and this option is not set, 0 will be used as - * the return value or callback response. This option is ignored on Windows. + * the return value or callback response. */ cancelId?: number; /** @@ -7957,7 +8457,7 @@ declare namespace Electron { /** * An icon to use in the notification. */ - icon?: string | NativeImage; + icon?: (string) | (NativeImage); /** * Whether or not to add an inline reply option to the notification. */ @@ -8025,6 +8525,16 @@ declare namespace Electron { urls: string[]; } + interface OnBeforeSendHeadersDetails { + id: number; + url: string; + method: string; + webContentsId?: number; + resourceType: string; + timestamp: number; + requestHeaders: RequestHeaders; + } + interface OnBeforeSendHeadersFilter { /** * Array of URL patterns that will be used to filter out the requests that do not @@ -8033,12 +8543,21 @@ declare namespace Electron { urls: string[]; } + interface OnBeforeSendHeadersResponse { + cancel?: boolean; + /** + * When provided, request will be made with these headers. + */ + requestHeaders?: RequestHeaders; + } + interface OnCompletedDetails { id: number; url: string; method: string; webContentsId?: number; resourceType: string; + referrer: string; timestamp: number; responseHeaders: ResponseHeaders; fromCache: boolean; @@ -8076,6 +8595,18 @@ declare namespace Electron { urls: string[]; } + interface OnHeadersReceivedDetails { + id: number; + url: string; + method: string; + webContentsId?: number; + resourceType: string; + timestamp: number; + statusLine: string; + statusCode: number; + responseHeaders: ResponseHeaders; + } + interface OnHeadersReceivedFilter { /** * Array of URL patterns that will be used to filter out the requests that do not @@ -8084,6 +8615,19 @@ declare namespace Electron { urls: string[]; } + interface OnHeadersReceivedResponse { + cancel?: boolean; + /** + * When provided, the server is assumed to have responded with these headers. + */ + responseHeaders?: ResponseHeaders; + /** + * Should be provided when overriding responseHeaders to change header status + * otherwise original response header's status will be used. + */ + statusLine?: string; + } + interface OnResponseStartedDetails { id: number; url: string; @@ -8163,7 +8707,11 @@ declare namespace Electron { /** * true to bring the opened application to the foreground. The default is true. */ - activate: boolean; + activate?: boolean; + /** + * The working directory. + */ + workingDirectory?: string; } interface PageFaviconUpdatedEvent extends Event { @@ -8188,8 +8736,8 @@ declare namespace Electron { */ screenSize: Size; /** - * Position the view on the screen (screenPosition == mobile) (default: {x: 0, y: - * 0}). + * Position the view on the screen (screenPosition == mobile) (default: { x: 0, y: + * 0 }). */ viewPosition: Point; /** @@ -8219,11 +8767,42 @@ declare namespace Electron { quantity: number; } + interface PermissionCheckHandlerDetails { + /** + * The security orign of the media check. + */ + securityOrigin: string; + /** + * The type of media access being requested, can be video, audio or unknown + */ + mediaType: ('video' | 'audio' | 'unknown'); + /** + * The last URL the requesting frame loaded + */ + requestingUrl: string; + /** + * Whether the frame making the request is the main frame + */ + isMainFrame: boolean; + } + interface PermissionRequestHandlerDetails { /** * The url of the openExternal request. */ - externalURL: string; + externalURL?: string; + /** + * The types of media access being requested, elements can be video or audio + */ + mediaTypes?: Array<'video' | 'audio'>; + /** + * The last URL the requesting frame loaded + */ + requestingUrl: string; + /** + * Whether the frame making the request is the main frame + */ + isMainFrame: boolean; } interface PluginCrashedEvent extends Event { @@ -8280,7 +8859,7 @@ declare namespace Electron { * Specify page size of the generated PDF. Can be A3, A4, A5, Legal, Letter, * Tabloid or an Object containing height and width in microns. */ - pageSize?: string | Size; + pageSize?: (string) | (Size); /** * Whether to print CSS backgrounds. */ @@ -8297,23 +8876,19 @@ declare namespace Electron { interface ProcessMemoryInfo { /** - * The amount of memory currently pinned to actual physical RAM. + * and The amount of memory currently pinned to actual physical RAM in Kilobytes. */ - workingSetSize: number; - /** - * The maximum amount of memory that has ever been pinned to actual physical RAM. - */ - peakWorkingSetSize: number; + residentSet: number; /** * The amount of memory not shared by other processes, such as JS heap or HTML - * content. + * content in Kilobytes. */ - privateBytes: number; + private: number; /** * The amount of memory shared between processes, typically memory consumed by the - * Electron code itself. + * Electron code itself in Kilobytes. */ - sharedBytes: number; + shared: number; } interface ProgressBarOptions { @@ -8358,6 +8933,7 @@ declare namespace Electron { interface RegisterHttpProtocolRequest { url: string; + headers: Headers; referrer: string; method: string; uploadData: UploadData[]; @@ -8546,11 +9122,6 @@ declare namespace Electron { traceOptions: string; } - interface StartRecordingOptions { - categoryFilter: string; - traceOptions: string; - } - interface SystemMemoryInfo { /** * The total amount of physical memory in Kilobytes available to the system. @@ -8630,8 +9201,8 @@ declare namespace Electron { } interface TouchBarConstructorOptions { - items: Array; - escapeItem?: TouchBarButton | TouchBarColorPicker | TouchBarGroup | TouchBarLabel | TouchBarPopover | TouchBarScrubber | TouchBarSegmentedControl | TouchBarSlider | TouchBarSpacer | null; + items: Array<(TouchBarButton) | (TouchBarColorPicker) | (TouchBarGroup) | (TouchBarLabel) | (TouchBarPopover) | (TouchBarScrubber) | (TouchBarSegmentedControl) | (TouchBarSlider) | (TouchBarSpacer)>; + escapeItem?: (TouchBarButton) | (TouchBarColorPicker) | (TouchBarGroup) | (TouchBarLabel) | (TouchBarPopover) | (TouchBarScrubber) | (TouchBarSegmentedControl) | (TouchBarSlider) | (TouchBarSpacer) | (null); } interface TouchBarGroupConstructorOptions { @@ -8797,6 +9368,13 @@ declare namespace Electron { electron?: string; } + interface VisibleOnAllWorkspacesOptions { + /** + * Sets whether the window should be visible above fullscreen windows + */ + visibleOnFullScreen?: boolean; + } + interface WillNavigateEvent extends Event { url: string; } @@ -8890,6 +9468,9 @@ declare namespace Electron { interface Options { } + interface Query { + } + interface RequestHeaders { } @@ -8930,6 +9511,10 @@ declare namespace Electron { * currently experimental and may change or be removed in future Electron releases. */ sandbox?: boolean; + /** + * Whether to enable the module. Default is true. + */ + enableRemoteModule?: boolean; /** * Sets the session used by the page. Instead of passing the Session object * directly, you can also choose to use the partition option instead, which accepts @@ -8998,10 +9583,6 @@ declare namespace Electron { * Enables Chromium's experimental features. Default is false. */ // experimentalFeatures?: boolean; ### VSCODE CHANGE (https://github.com/electron/electron/blob/master/docs/tutorial/security.md) ### - /** - * Enables Chromium's experimental canvas features. Default is false. - */ - experimentalCanvasFeatures?: boolean; /** * Enables scroll bounce (rubber banding) effect on macOS. Default is false. */ @@ -9057,8 +9638,7 @@ declare namespace Electron { * content to ensure the loaded content cannot tamper with the preload script and * any Electron APIs being used. This option uses the same technique used by . You * can access this context in the dev tools by selecting the 'Electron Isolated - * Context' entry in the combo box at the top of the Console tab. This option is - * currently experimental and may change or be removed in future Electron releases. + * Context' entry in the combo box at the top of the Console tab. */ contextIsolation?: boolean; /** @@ -9070,11 +9650,11 @@ declare namespace Electron { nativeWindowOpen?: boolean; /** * Whether to enable the . Defaults to the value of the nodeIntegration option. The - * preload script configured for the will have node integration enabled - * when it is executed so you should ensure remote/untrusted content is not able to - * create a tag with a possibly malicious preload script. You can use the + * preload script configured for the will have node integration enabled when it is + * executed so you should ensure remote/untrusted content is not able to create a + * tag with a possibly malicious preload script. You can use the * will-attach-webview event on to strip away the preload script and to validate or - * alter the 's initial settings. + * alter the 's initial settings. */ webviewTag?: boolean; /** @@ -9156,7 +9736,7 @@ interface Document { declare namespace NodeJS { interface Process extends EventEmitter { - // Docs: http://electron.atom.io/docs/api/process + // Docs: http://electronjs.org/docs/api/process // ### BEGIN VSCODE MODIFICATION ### // /** @@ -9176,6 +9756,12 @@ declare namespace NodeJS { */ crash(): void; getCPUUsage(): Electron.CPUUsage; + /** + * Indicates the creation time of the application. The time is represented as + * number of milliseconds since epoch. It returns null if it is unable to get the + * process creation time. + */ + getCreationTime(): (number) | (null); /** * Returns an object with V8 heap statistics. Note that all statistics are reported * in Kilobytes. @@ -9184,7 +9770,12 @@ declare namespace NodeJS { getIOCounters(): Electron.IOCounters; /** * Returns an object giving memory usage statistics about the current process. Note - * that all statistics are reported in Kilobytes. + * that all statistics are reported in Kilobytes. This api should be called after + * app ready. Chromium does not provide residentSet value for macOS. This is + * because macOS performs in-memory compression of pages that haven't been recently + * used. As a result the resident set size value is not what one would expect. + * private memory is more representative of the actual pre-compression memory usage + * of the process on macOS. */ getProcessMemoryInfo(): Electron.ProcessMemoryInfo; /** @@ -9201,6 +9792,10 @@ declare namespace NodeJS { * whichever is lower for the current process. */ setFdLimit(maxDescriptors: number): void; + /** + * Takes a V8 heap snapshot and saves it to filePath. + */ + takeHeapSnapshot(filePath: string): boolean; /** * A Boolean. When app is started by being passed as parameter to the default app, * this property is true in the main process, otherwise it is undefined. @@ -9226,6 +9821,11 @@ declare namespace NodeJS { * A String representing the path to the resources directory. */ resourcesPath?: string; + /** + * A Boolean. When the renderer process is sandboxed, this property is true, + * otherwise it is undefined. + */ + sandboxed?: boolean; /** * A Boolean that controls whether or not deprecation warnings will be thrown as * exceptions. Setting this to true will throw errors for deprecations. This @@ -9261,4 +9861,4 @@ declare namespace NodeJS { electron: string; chrome: string; } -} +} \ No newline at end of file diff --git a/src/typings/es6-promise.d.ts b/src/typings/es6-promise.d.ts index f674baa6a87..2d3271e2848 100644 --- a/src/typings/es6-promise.d.ts +++ b/src/typings/es6-promise.d.ts @@ -44,7 +44,12 @@ declare namespace Promise { * Make a new promise from the thenable. * A thenable is promise-like in as far as it has a "then" method. */ - function resolve(value?: T | Thenable): Promise; + function resolve(value: T | Thenable): Promise; + + /** + * + */ + function resolve(): Promise; /** * Make a promise that rejects to obj. For consistency and debugging (eg stack traces), obj should be an instanceof Error diff --git a/src/typings/fast-plist.d.ts b/src/typings/fast-plist.d.ts deleted file mode 100644 index 537e7c2e8ec..00000000000 --- a/src/typings/fast-plist.d.ts +++ /dev/null @@ -1,7 +0,0 @@ - -declare module "fast-plist" { - /** - * A very fast plist parser - */ - export function parse(content: string): any; -} diff --git a/src/typings/gc-signals.d.ts b/src/typings/gc-signals.d.ts deleted file mode 100644 index 15af0411773..00000000000 --- a/src/typings/gc-signals.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -declare module 'gc-signals' { - export interface GCSignal { - } - /** - * Create a new GC signal. When being garbage collected the passed - * value is stored for later consumption. - */ - export const GCSignal: { - new(id: number): GCSignal; - }; - /** - * Consume ids of garbage collected signals. - */ - export function consumeSignals(): number[]; - export function onDidGarbageCollectSignals(callback: (ids: number[]) => any): { - dispose(): void; - }; - export function trackGarbageCollection(obj: any, id: number): number; -} \ No newline at end of file diff --git a/src/typings/lib.array-ext.d.ts b/src/typings/lib.array-ext.d.ts index 127f64e1fd4..5a77b70a9f2 100644 --- a/src/typings/lib.array-ext.d.ts +++ b/src/typings/lib.array-ext.d.ts @@ -4,6 +4,8 @@ *--------------------------------------------------------------------------------------------*/ interface ArrayConstructor { + isArray(arg: ReadonlyArray | null | undefined): arg is ReadonlyArray; + isArray(arg: Array | null | undefined): arg is Array; isArray(arg: any): arg is Array; isArray(arg: any): arg is Array; } \ No newline at end of file diff --git a/src/typings/lib.es2018.promise.d.ts b/src/typings/lib.es2018.promise.d.ts new file mode 100644 index 00000000000..9f7b2d38cb2 --- /dev/null +++ b/src/typings/lib.es2018.promise.d.ts @@ -0,0 +1,27 @@ +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + +/** + * Represents the completion of an asynchronous operation + */ +interface Promise { + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): Promise; +} diff --git a/src/typings/lib.ie11_safe_es6.d.ts b/src/typings/lib.ie11_safe_es6.d.ts index e4f8fc57e76..43bde6f7c64 100644 --- a/src/typings/lib.ie11_safe_es6.d.ts +++ b/src/typings/lib.ie11_safe_es6.d.ts @@ -10,7 +10,7 @@ interface Map { clear(): void; delete(key: K): boolean; forEach(callbackfn: (value: V, index: K, map: Map) => void, thisArg?: any): void; - get(key: K): V; + get(key: K): V | undefined; has(key: K): boolean; set(key: K, value?: V): Map; readonly size: number; @@ -59,7 +59,7 @@ interface SetConstructor { declare var Set: SetConstructor; -interface WeakMap { +interface WeakMap { delete(key: K): boolean; get(key: K): V | undefined; has(key: K): boolean; @@ -70,9 +70,9 @@ interface WeakMap { interface WeakMapConstructor { new(): WeakMap; - new (): WeakMap; + new (): WeakMap; // new (entries?: [K, V][]): WeakMap; - readonly prototype: WeakMap; + readonly prototype: WeakMap; } declare var WeakMap: WeakMapConstructor; diff --git a/src/typings/lib.webworker.importscripts.d.ts b/src/typings/lib.webworker.importscripts.d.ts new file mode 100644 index 00000000000..e84f717c9a4 --- /dev/null +++ b/src/typings/lib.webworker.importscripts.d.ts @@ -0,0 +1,23 @@ +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + + + + +///////////////////////////// +/// WorkerGlobalScope APIs +///////////////////////////// +// These are only available in a Web Worker +declare function importScripts(...urls: string[]): void; diff --git a/src/typings/node-pty.d.ts b/src/typings/node-pty.d.ts index 8eeb51e3b37..2e6d6cfdc5f 100644 --- a/src/typings/node-pty.d.ts +++ b/src/typings/node-pty.d.ts @@ -1,5 +1,6 @@ /** * Copyright (c) 2017, Daniel Imms (MIT License). + * Copyright (c) 2018, Microsoft Corporation (MIT License). */ declare module 'node-pty' { @@ -11,76 +12,132 @@ declare module 'node-pty' { * escaped properly. * @param options The options of the terminal. * @see CommandLineToArgvW https://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx - * @see Parsing C++ Command-Line Arguments https://msdn.microsoft.com/en-us/library/17w5ykft.aspx + * @see Parsing C++ Comamnd-Line Arguments https://msdn.microsoft.com/en-us/library/17w5ykft.aspx * @see GetCommandLine https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156.aspx */ - export function spawn(file: string, args: string[] | string, options: IPtyForkOptions): IPty; + export function spawn(file: string, args: string[] | string, options: IPtyForkOptions | IWindowsPtyForkOptions): IPty; export interface IPtyForkOptions { - name?: string; - cols?: number; - rows?: number; - cwd?: string; - env?: { [key: string]: string }; - uid?: number; - gid?: number; - encoding?: string; - /** - * Whether to use the experimental ConPTY system on Windows. This setting will be ignored on - * non-Windows. - */ - experimentalUseConpty?: boolean; + name?: string; + cols?: number; + rows?: number; + cwd?: string; + env?: { [key: string]: string }; + uid?: number; + gid?: number; + encoding?: string; + } + + export interface IWindowsPtyForkOptions { + name?: string; + cols?: number; + rows?: number; + cwd?: string; + env?: { [key: string]: string }; + encoding?: string; + /** + * Whether to use the experimental ConPTY system on Windows. When this is not set, ConPTY will + * be used when the Windows build number is >= 18309 (it's available in 17134 and 17692 but is + * too unstable to enable by default). + * + * This setting does nothing on non-Windows. + */ + experimentalUseConpty?: boolean; + /** + * Whether to use PSEUDOCONSOLE_INHERIT_CURSOR in conpty. + * @see https://docs.microsoft.com/en-us/windows/console/createpseudoconsole + */ + conptyInheritCursor?: boolean; } /** * An interface representing a pseudoterminal, on Windows this is emulated via the winpty library. */ export interface IPty { - /** - * The process ID of the outer process. - */ - pid: number; + /** + * The process ID of the outer process. + */ + readonly pid: number; - /** - * The title of the active process. - */ - process: string; + /** + * The column size in characters. + */ + readonly cols: number; - /** - * Adds a listener to the data event, fired when data is returned from the pty. - * @param event The name of the event. - * @param listener The callback function. - */ - on(event: 'data', listener: (data: string) => void): void; + /** + * The row size in characters. + */ + readonly rows: number; - /** - * Adds a listener to the exit event, fired when the pty exits. - * @param event The name of the event. - * @param listener The callback function, exitCode is the exit code of the process and signal is - * the signal that triggered the exit. signal is not supported on Windows. - */ - on(event: 'exit', listener: (exitCode: number, signal?: number) => void): void; + /** + * The title of the active process. + */ + readonly process: string; - /** - * Resizes the dimensions of the pty. - * @param columns The number of columns to use. - * @param rows The number of rows to use. - */ - resize(columns: number, rows: number): void; + /** + * Adds an event listener for when a data event fires. This happens when data is returned from + * the pty. + * @returns an `IDisposable` to stop listening. + */ + readonly onData: IEvent; - /** - * Writes data to the pty. - * @param data The data to write. - */ - write(data: string): void; + /** + * Adds an event listener for when an exit event fires. This happens when the pty exits. + * @returns an `IDisposable` to stop listening. + */ + readonly onExit: IEvent<{ exitCode: number, signal?: number }>; - /** - * Kills the pty. - * @param signal The signal to use, defaults to SIGHUP. If the TIOCSIG/TIOCSIGNAL ioctl is not - * supported then the process will be killed instead. This parameter is not supported on - * Windows. - * @throws Will throw when signal is used on Windows. - */ - kill(signal?: string): void; + /** + * Adds a listener to the data event, fired when data is returned from the pty. + * @param event The name of the event. + * @param listener The callback function. + * @deprecated Use IPty.onData + */ + on(event: 'data', listener: (data: string) => void): void; + + /** + * Adds a listener to the exit event, fired when the pty exits. + * @param event The name of the event. + * @param listener The callback function, exitCode is the exit code of the process and signal is + * the signal that triggered the exit. signal is not supported on Windows. + * @deprecated Use IPty.onExit + */ + on(event: 'exit', listener: (exitCode: number, signal?: number) => void): void; + + /** + * Resizes the dimensions of the pty. + * @param columns THe number of columns to use. + * @param rows The number of rows to use. + */ + resize(columns: number, rows: number): void; + + /** + * Writes data to the pty. + * @param data The data to write. + */ + write(data: string): void; + + /** + * Kills the pty. + * @param signal The signal to use, defaults to SIGHUP. This parameter is not supported on + * Windows. + * @throws Will throw when signal is used on Windows. + */ + kill(signal?: string): void; } - } \ No newline at end of file + + /** + * An object that can be disposed via a dispose function. + */ + export interface IDisposable { + dispose(): void; + } + + /** + * An event that can be listened to. + * @returns an `IDisposable` to stop listening. + */ + export interface IEvent { + (listener: (e: T) => any): IDisposable; + } +} diff --git a/src/typings/vscode-nsfw.d.ts b/src/typings/nsfw.d.ts similarity index 95% rename from src/typings/vscode-nsfw.d.ts rename to src/typings/nsfw.d.ts index 5f70eb30f7b..f8bb423a2f8 100644 --- a/src/typings/vscode-nsfw.d.ts +++ b/src/typings/nsfw.d.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -declare module 'vscode-nsfw' { +declare module 'nsfw' { interface NsfwWatcher { start(): any; stop(): any; @@ -22,6 +22,7 @@ declare module 'vscode-nsfw' { directory: string; file?: string; newFile?: string; + newDirectory?: string; oldFile?: string; } diff --git a/src/typings/onigasm-umd.d.ts b/src/typings/onigasm-umd.d.ts new file mode 100644 index 00000000000..151cecebfdd --- /dev/null +++ b/src/typings/onigasm-umd.d.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module "onigasm-umd" { + + function loadWASM(data: string | ArrayBuffer): Promise; + + class OnigString { + constructor(content: string); + readonly content: string; + readonly dispose?: () => void; + } + + class OnigScanner { + constructor(patterns: string[]); + findNextMatchSync(string: string | OnigString, startPosition: number): IOnigMatch; + } + + export interface IOnigCaptureIndex { + index: number + start: number + end: number + length: number + } + + export interface IOnigMatch { + index: number + captureIndices: IOnigCaptureIndex[] + scanner: OnigScanner + } +} \ No newline at end of file diff --git a/src/typings/require.d.ts b/src/typings/require.d.ts index ded5e2e7270..618861a5bee 100644 --- a/src/typings/require.d.ts +++ b/src/typings/require.d.ts @@ -17,7 +17,12 @@ declare const enum LoaderEventType { NodeEndEvaluatingScript = 32, NodeBeginNativeRequire = 33, - NodeEndNativeRequire = 34 + NodeEndNativeRequire = 34, + + CachedDataFound = 60, + CachedDataMissed = 61, + CachedDataRejected = 62, + CachedDataCreated = 63, } declare class LoaderEvent { diff --git a/extensions/json-language-features/server/build/filesFillIn.js b/src/typings/semver-umd.d.ts similarity index 85% rename from extensions/json-language-features/server/build/filesFillIn.js rename to src/typings/semver-umd.d.ts index 906617384e0..372f000c617 100644 --- a/extensions/json-language-features/server/build/filesFillIn.js +++ b/src/typings/semver-umd.d.ts @@ -2,4 +2,9 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -module.exports = {}; \ No newline at end of file + +declare module 'semver-umd' { + + export * from "semver"; + +} \ No newline at end of file diff --git a/src/typings/spdlog.d.ts b/src/typings/spdlog.d.ts index 4762b11143f..bf6bb9c3dfd 100644 --- a/src/typings/spdlog.d.ts +++ b/src/typings/spdlog.d.ts @@ -6,7 +6,9 @@ declare module 'spdlog' { export const version: string; - export function setAsyncMode(bufferSize: number, flushInterval: number); + export function setAsyncMode(bufferSize: number, flushInterval: number): void; + export function createRotatingLogger(name: string, filename: string, filesize: number, filecount: number): RotatingLogger; + export function createRotatingLoggerAsync(name: string, filename: string, filesize: number, filecount: number): Promise; export enum LogLevel { CRITICAL, @@ -21,14 +23,14 @@ declare module 'spdlog' { export class RotatingLogger { constructor(name: string, filename: string, filesize: number, filecount: number); - trace(message: string); - debug(message: string); - info(message: string); - warn(message: string); - error(message: string); - critical(message: string); - setLevel(level: number); - clearFormatters(); + trace(message: string): void; + debug(message: string): void; + info(message: string): void; + warn(message: string): void; + error(message: string): void; + critical(message: string): void; + setLevel(level: number): void; + clearFormatters(): void; /** * A synchronous operation to flush the contents into file */ diff --git a/src/typings/sudo-prompt.d.ts b/src/typings/sudo-prompt.d.ts index 4a204229051..85f9783d0a6 100644 --- a/src/typings/sudo-prompt.d.ts +++ b/src/typings/sudo-prompt.d.ts @@ -5,5 +5,5 @@ declare module 'sudo-prompt' { - export function exec(cmd: string, options: { name?: string, icns?: string }, callback: (error: string, stdout: string, stderr: string) => void); + export function exec(cmd: string, options: { name?: string, icns?: string }, callback: (error: string, stdout: string, stderr: string) => void): void; } \ No newline at end of file diff --git a/src/typings/vscode-minimist.d.ts b/src/typings/vscode-minimist.d.ts new file mode 100644 index 00000000000..17558a1a738 --- /dev/null +++ b/src/typings/vscode-minimist.d.ts @@ -0,0 +1,92 @@ +// Type definitions for minimist 1.2.0 +// Project: https://github.com/substack/minimist +// Definitions by: Bart van der Schoor , Necroskillz , kamranayub +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/** + * Return an argument object populated with the array arguments from args + * + * @param args An optional argument array (typically `process.argv.slice(2)`) + * @param opts An optional options object to customize the parsing + */ +declare function minimist(args?: string[], opts?: minimist.Opts): minimist.ParsedArgs; + +/** + * Return an argument object populated with the array arguments from args. Strongly-typed + * to be the intersect of type T with minimist.ParsedArgs. + * + * @type T The type that will be intersected with minimist.ParsedArgs to represent the argument object + * @param args An optional argument array (typically `process.argv.slice(2)`) + * @param opts An optional options object to customize the parsing + */ +declare function minimist(args?: string[], opts?: minimist.Opts): T & minimist.ParsedArgs; + +/** + * Return an argument object populated with the array arguments from args. Strongly-typed + * to be the the type T which should extend minimist.ParsedArgs + * + * @type T The type that extends minimist.ParsedArgs and represents the argument object + * @param args An optional argument array (typically `process.argv.slice(2)`) + * @param opts An optional options object to customize the parsing + */ +declare function minimist(args?: string[], opts?: minimist.Opts): T; + +declare namespace minimist { + export interface Opts { + /** + * A string or array of strings argument names to always treat as strings + */ + string?: string | string[]; + + /** + * A boolean, string or array of strings to always treat as booleans. If true will treat + * all double hyphenated arguments without equals signs as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`) + */ + boolean?: boolean | string | string[]; + + /** + * An object mapping string names to strings or arrays of string argument names to use as aliases + */ + alias?: { [key: string]: string | string[] }; + + /** + * An object mapping string argument names to default values + */ + default?: { [key: string]: any }; + + /** + * When true, populate argv._ with everything after the first non-option + */ + stopEarly?: boolean; + + /** + * A function which is invoked with a command line parameter not defined in the opts + * configuration object. If the function returns false, the unknown option is not added to argv + */ + unknown?: (arg: string) => boolean; + + /** + * When true, populate argv._ with everything before the -- and argv['--'] with everything after the --. + * Note that with -- set, parsing for arguments still stops after the `--`. + */ + '--'?: boolean; + } + + export interface ParsedArgs { + [arg: string]: any; + + /** + * If opts['--'] is true, populated with everything after the -- + */ + '--'?: string[]; + + /** + * Contains all the arguments that didn't have an option associated with them + */ + _: string[]; + } +} + +declare module "vscode-minimist" { + export = minimist; +} diff --git a/src/typings/vscode-sqlite3.d.ts b/src/typings/vscode-sqlite3.d.ts index 4363d251c46..9a79c4ded1c 100644 --- a/src/typings/vscode-sqlite3.d.ts +++ b/src/typings/vscode-sqlite3.d.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Type definitions for sqlite3 3.1 -// Project: https://github.com/mapbox/node-sqlite3 +// Project: http://github.com/mapbox/node-sqlite3 // Definitions by: Nick Malaguti // Sumant Manne // Behind The Math @@ -18,6 +18,9 @@ declare module 'vscode-sqlite3' { export const OPEN_READONLY: number; export const OPEN_READWRITE: number; export const OPEN_CREATE: number; + export const OPEN_SHAREDCACHE: number; + export const OPEN_PRIVATECACHE: number; + export const OPEN_URI: number; export const cached: { Database(filename: string, callback?: (this: Database, err: Error | null) => void): Database; @@ -100,6 +103,9 @@ declare module 'vscode-sqlite3' { OPEN_READONLY: number; OPEN_READWRITE: number; OPEN_CREATE: number; + OPEN_SHAREDCACHE: number; + OPEN_PRIVATECACHE: number; + OPEN_URI: number; cached: typeof cached; RunResult: RunResult; Statement: typeof Statement; diff --git a/src/typings/vscode-textmate.d.ts b/src/typings/vscode-textmate.d.ts index 224b9100482..835b33008ac 100644 --- a/src/typings/vscode-textmate.d.ts +++ b/src/typings/vscode-textmate.d.ts @@ -30,7 +30,7 @@ declare module "vscode-textmate" { */ export interface RegistryOptions { theme?: IRawTheme; - loadGrammar(scopeName: string): Thenable | null; + loadGrammar(scopeName: string): Thenable; getInjections?(scopeName: string): string[]; getOnigLib?(): Thenable; } @@ -85,7 +85,7 @@ declare module "vscode-textmate" { * Load the grammar for `scopeName` and all referenced included grammars asynchronously. */ loadGrammar(initialScopeName: string): Thenable; - private _loadGrammar(initialScopeName, initialLanguage, embeddedLanguages, tokenTypes); + private _loadGrammar; /** * Adds a rawGrammar. */ @@ -182,7 +182,7 @@ declare module "vscode-textmate" { equals(other: StackElement): boolean; } export const INITIAL: StackElement; - export const parseRawGrammar: (content: string, filePath: string) => IRawGrammar; + export const parseRawGrammar: (content: string, filePath?: string) => IRawGrammar; export interface ILocation { readonly filename: string; readonly line: number; diff --git a/extensions/css-language-features/server/build/filesFillIn.js b/src/typings/vscode-windows-ca-certs.d.ts similarity index 89% rename from extensions/css-language-features/server/build/filesFillIn.js rename to src/typings/vscode-windows-ca-certs.d.ts index 906617384e0..f923eb8a8ac 100644 --- a/extensions/css-language-features/server/build/filesFillIn.js +++ b/src/typings/vscode-windows-ca-certs.d.ts @@ -2,4 +2,5 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -module.exports = {}; \ No newline at end of file + +declare module 'vscode-windows-ca-certs'; diff --git a/src/typings/vscode-windows-registry.d.ts b/src/typings/vscode-windows-registry.d.ts new file mode 100644 index 00000000000..9be14daa4b2 --- /dev/null +++ b/src/typings/vscode-windows-registry.d.ts @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode-windows-registry' { + export type HKEY = "HKEY_CURRENT_USER" | "HKEY_LOCAL_MACHINE" | "HKEY_CLASSES_ROOT" | "HKEY_USERS" | "HKEY_CURRENT_CONFIG"; + export function GetStringRegKey(hive: HKEY, path: string, name: string): string | undefined; +} \ No newline at end of file diff --git a/src/vs/workbench/parts/update/electron-browser/media/update.contribution.css b/src/typings/vsda.d.ts similarity index 82% rename from src/vs/workbench/parts/update/electron-browser/media/update.contribution.css rename to src/typings/vsda.d.ts index 486837877ef..369e98483b6 100644 --- a/src/vs/workbench/parts/update/electron-browser/media/update.contribution.css +++ b/src/typings/vsda.d.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.update-activity { - -webkit-mask: url('update.svg') no-repeat 50% 50%; +declare module 'vsda' { + export class signer { + sign(arg: any): any; + } } diff --git a/src/typings/xterm-addon-search.d.ts b/src/typings/xterm-addon-search.d.ts new file mode 100644 index 00000000000..2f3be6f82bd --- /dev/null +++ b/src/typings/xterm-addon-search.d.ts @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +// HACK: gulp-tsb doesn't play nice with importing from typings +// import { Terminal, ITerminalAddon } from 'xterm'; + +declare module 'xterm-addon-search' { + /** + * Options for a search. + */ + export interface ISearchOptions { + /** + * Whether the search term is a regex. + */ + regex?: boolean; + + /** + * Whether to search for a whole word, the result is only valid if it's + * suppounded in "non-word" characters such as `_`, `(`, `)` or space. + */ + wholeWord?: boolean; + + /** + * Whether the search is case sensitive. + */ + caseSensitive?: boolean; + + /** + * Whether to do an indcremental search, this will expand the selection if it + * still matches the term the user typed. Note that this only affects + * `findNext`, not `findPrevious`. + */ + incremental?: boolean; + } + + /** + * An xterm.js addon that provides search functionality. + */ + export class SearchAddon { + /** + * Activates the addon + * @param terminal The terminal the addon is being loaded in. + */ + public activate(terminal: any): void; + + /** + * Disposes the addon. + */ + public dispose(): void; + + /** + * Search forwards for the next result that matches the search term and + * options. + * @param term The search term. + * @param searchOptions The options for the search. + */ + public findNext(term: string, searchOptions?: ISearchOptions): boolean; + + /** + * Search backwards for the previous result that matches the search term and + * options. + * @param term The search term. + * @param searchOptions The options for the search. + */ + public findPrevious(term: string, searchOptions?: ISearchOptions): boolean; + } +} diff --git a/src/typings/xterm-addon-web-links.d.ts b/src/typings/xterm-addon-web-links.d.ts new file mode 100644 index 00000000000..da348f8c82e --- /dev/null +++ b/src/typings/xterm-addon-web-links.d.ts @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +// HACK: gulp-tsb doesn't play nice with importing from typings +// import { Terminal, ITerminalAddon } from 'xterm'; +interface ILinkMatcherOptions { + /** + * The index of the link from the regex.match(text) call. This defaults to 0 + * (for regular expressions without capture groups). + */ + matchIndex?: number; + + /** + * A callback that validates whether to create an individual link, pass + * whether the link is valid to the callback. + */ + validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void; + + /** + * A callback that fires when the mouse hovers over a link for a moment. + */ + tooltipCallback?: (event: MouseEvent, uri: string) => boolean | void; + + /** + * A callback that fires when the mouse leaves a link. Note that this can + * happen even when tooltipCallback hasn't fired for the link yet. + */ + leaveCallback?: () => void; + + /** + * The priority of the link matcher, this defines the order in which the link + * matcher is evaluated relative to others, from highest to lowest. The + * default value is 0. + */ + priority?: number; + + /** + * A callback that fires when the mousedown and click events occur that + * determines whether a link will be activated upon click. This enables + * only activating a link when a certain modifier is held down, if not the + * mouse event will continue propagation (eg. double click to select word). + */ + willLinkActivate?: (event: MouseEvent, uri: string) => boolean; +} + +declare module 'xterm-addon-web-links' { + /** + * An xterm.js addon that enables web links. + */ + export class WebLinksAddon { + /** + * Creates a new web links addon. + * @param handler The callback when the link is called. + * @param options Options for the link matcher. + */ + constructor(handler?: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions); + + /** + * Activates the addon + * @param terminal The terminal the addon is being loaded in. + */ + public activate(terminal: any): void; + + /** + * Disposes the addon. + */ + public dispose(): void; + } +} diff --git a/src/typings/vscode-xterm.d.ts b/src/typings/xterm.d.ts similarity index 59% rename from src/typings/vscode-xterm.d.ts rename to src/typings/xterm.d.ts index e425a37c43f..663b997022b 100644 --- a/src/typings/vscode-xterm.d.ts +++ b/src/typings/xterm.d.ts @@ -9,12 +9,17 @@ /// -declare module 'vscode-xterm' { +declare module 'xterm' { /** * A string representing text font weight. */ export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; + /** + * A string representing log level. + */ + export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'off'; + /** * A string representing a renderer type. */ @@ -26,13 +31,14 @@ declare module 'vscode-xterm' { export interface ITerminalOptions { /** * Whether background should support non-opaque color. It must be set before - * executing open() method and can't be changed later without excuting it again. - * Warning: Enabling this option can reduce performances somewhat. + * executing the `Terminal.open()` method and can't be changed later without + * executing it again. Note that enabling this can negatively impact + * performance. */ allowTransparency?: boolean; /** - * A data uri of the sound to use for the bell (needs bellStyle = 'sound'). + * A data uri of the sound to use for the bell when `bellStyle = 'sound'`. */ bellSound?: string; @@ -76,42 +82,6 @@ declare module 'vscode-xterm' { */ drawBoldTextInBrightColors?: boolean; - /** - * Whether to enable the rendering of bold text. - * - * @deprecated Use fontWeight and fontWeightBold instead. - */ - enableBold?: boolean; - - /** - * What character atlas implementation to use. The character atlas caches drawn characters, - * speeding up rendering significantly. However, it can introduce some minor rendering - * artifacts. - * - * - 'none': Don't use an atlas. - * - 'static': Generate an atlas when the terminal starts or is reconfigured. This atlas will - * only contain ASCII characters in 16 colors. - * - 'dynamic': Generate an atlas using a LRU cache as characters are requested. Limited to - * ASCII characters (for now), but supports 256 colors. For characters covered by the static - * cache, it's slightly slower in comparison, since there's more overhead involved in - * managing the cache. - * - * Currently defaults to 'static'. This option may be removed in the future. If it is, passed - * parameters will be ignored. - */ - experimentalCharAtlas?: 'none' | 'static' | 'dynamic'; - - /** - * (EXPERIMENTAL) Defines which implementation to use for buffer lines. - * - * - 'JsArray': The default/stable implementation. - * - 'TypedArray': The new experimental implementation based on TypedArrays that is expected to - * significantly boost performance and memory consumption. Use at your own risk. - * - * @deprecated This option will be removed in the future. - */ - experimentalBufferLineImpl?: 'JsArray' | 'TypedArray'; - /** * The font size used to render text. */ @@ -142,6 +112,18 @@ declare module 'vscode-xterm' { */ lineHeight?: number; + /** + * What log level to use, this will log for all levels below and including + * what is set: + * + * 1. debug + * 2. info (default) + * 3. warn + * 4. error + * 5. off + */ + logLevel?: LogLevel; + /** * Whether to treat option as the meta key. */ @@ -150,9 +132,9 @@ declare module 'vscode-xterm' { /** * Whether holding a modifier key will force normal selection behavior, * regardless of whether the terminal is in mouse events mode. This will - * also prevent mouse events from being emitted by the terminal. For example, - * this allows you to use xterm.js' regular selection inside tmux with - * mouse mode enabled. + * also prevent mouse events from being emitted by the terminal. For + * example, this allows you to use xterm.js' regular selection inside tmux + * with mouse mode enabled. */ macOptionClickForcesSelection?: boolean; @@ -185,8 +167,9 @@ declare module 'vscode-xterm' { screenReaderMode?: boolean; /** - * The amount of scrollback in the terminal. Scrollback is the amount of rows - * that are retained when lines are scrolled beyond the initial viewport. + * The amount of scrollback in the terminal. Scrollback is the amount of + * rows that are retained when lines are scrolled beyond the initial + * viewport. */ scrollback?: number; @@ -199,6 +182,24 @@ declare module 'vscode-xterm' { * The color theme of the terminal. */ theme?: ITheme; + + /** + * Whether "Windows mode" is enabled. Because Windows backends winpty and + * conpty operate by doing line wrapping on their side, xterm.js does not + * have access to wrapped lines. When Windows mode is enabled the following + * changes will be in effect: + * + * - Reflow is disabled. + * - Lines are assumed to be wrapped if the last character of the line is + * not whitespace. + */ + windowsMode?: boolean; + + /** + * A string containing all characters that are considered word separated by the + * double click to select work logic. + */ + wordSeparator?: string; } /** @@ -211,9 +212,9 @@ declare module 'vscode-xterm' { background?: string, /** The cursor color */ cursor?: string, - /** The accent color of the cursor (used as the foreground color for a block cursor) */ + /** The accent color of the cursor (fg color for a block cursor) */ cursorAccent?: string, - /** The selection color (can be transparent) */ + /** The selection background color (can be transparent) */ selection?: string, /** ANSI black (eg. `\x1b[30m`) */ black?: string, @@ -274,11 +275,11 @@ declare module 'vscode-xterm' { * A callback that fires when the mouse leaves a link. Note that this can * happen even when tooltipCallback hasn't fired for the link yet. */ - leaveCallback?: (event: MouseEvent, uri: string) => boolean | void; + leaveCallback?: () => void; /** - * The priority of the link matcher, this defines the order in which the link - * matcher is evaluated relative to others, from highest to lowest. The + * The priority of the link matcher, this defines the order in which the + * link matcher is evaluated relative to others, from highest to lowest. The * default value is 0. */ priority?: number; @@ -292,13 +293,6 @@ declare module 'vscode-xterm' { willLinkActivate?: (event: MouseEvent, uri: string) => boolean; } - export interface IEventEmitter { - on(type: string, listener: (...args: any[]) => void): void; - off(type: string, listener: (...args: any[]) => void): void; - emit(type: string, data?: any): void; - addDisposableListener(type: string, handler: (...args: any[]) => void): IDisposable; - } - /** * An object that can be disposed via a dispose function. */ @@ -306,47 +300,91 @@ declare module 'vscode-xterm' { dispose(): void; } + /** + * An event that can be listened to. + * @returns an `IDisposable` to stop listening. + */ + export interface IEvent { + (listener: (e: T) => any): IDisposable; + } + + /** + * Represents a specific line in the terminal that is tracked when scrollback + * is trimmed and lines are added or removed. + */ export interface IMarker extends IDisposable { + /** + * A unique identifier for this marker. + */ readonly id: number; + + /** + * Whether this marker is disposed. + */ readonly isDisposed: boolean; + + /** + * The actual line index in the buffer at this point in time. + */ readonly line: number; } + /** + * The set of localizable strings. + */ export interface ILocalizableStrings { - blankLine: string; + /** + * The aria label for the underlying input textarea for the terminal. + */ promptLabel: string; + + /** + * Announcement for when line reading is suppressed due to too many lines + * being printed to the terminal when `screenReaderMode` is enabled. + */ tooMuchOutput: string; } /** * The class that represents an xterm.js terminal. */ - export class Terminal implements IEventEmitter, IDisposable { + export class Terminal implements IDisposable { /** * The element containing the terminal. */ - element: HTMLElement; + readonly element: HTMLElement; /** * The textarea that accepts input for the terminal. */ - textarea: HTMLTextAreaElement; + readonly textarea: HTMLTextAreaElement; /** - * The number of rows in the terminal's viewport. + * The number of rows in the terminal's viewport. Use + * `ITerminalOptions.rows` to set this in the constructor and + * `Terminal.resize` for when the terminal exists. */ - rows: number; + readonly rows: number; /** - * The number of columns in the terminal's viewport. + * The number of columns in the terminal's viewport. Use + * `ITerminalOptions.cols` to set this in the constructor and + * `Terminal.resize` for when the terminal exists. */ - cols: number; + readonly cols: number; + + /** + * (EXPERIMENTAL) The terminal's current buffer, this might be either the + * normal buffer or the alt buffer depending on what's running in the + * terminal. + */ + readonly buffer: IBuffer; /** * (EXPERIMENTAL) Get all markers registered against the buffer. If the alt * buffer is active this will always return []. */ - markers: IMarker[]; + readonly markers: ReadonlyArray; /** * Natural language strings that can be localized. @@ -360,6 +398,70 @@ declare module 'vscode-xterm' { */ constructor(options?: ITerminalOptions); + /** + * Adds an event listener for the cursor moves. + * @returns an `IDisposable` to stop listening. + */ + onCursorMove: IEvent; + + /** + * Adds an event listener for when a data event fires. This happens for + * example when the user types or pastes into the terminal. The event value + * is whatever `string` results, in a typical setup, this should be passed + * on to the backing pty. + * @returns an `IDisposable` to stop listening. + */ + onData: IEvent; + + /** + * Adds an event listener for a key is pressed. The event value contains the + * string that will be sent in the data event as well as the DOM event that + * triggered it. + * @returns an `IDisposable` to stop listening. + */ + onKey: IEvent<{ key: string, domEvent: KeyboardEvent }>; + + /** + * Adds an event listener for when a line feed is added. + * @returns an `IDisposable` to stop listening. + */ + onLineFeed: IEvent; + + /** + * Adds an event listener for when a scroll occurs. The event value is the + * new position of the viewport. + * @returns an `IDisposable` to stop listening. + */ + onScroll: IEvent; + + /** + * Adds an event listener for when a selection change occurs. + * @returns an `IDisposable` to stop listening. + */ + onSelectionChange: IEvent; + + /** + * Adds an event listener for when rows are rendered. The event value + * contains the start row and end rows of the rendered area (ranges from `0` + * to `Terminal.rows - 1`). + * @returns an `IDisposable` to stop listening. + */ + onRender: IEvent<{ start: number, end: number }>; + + /** + * Adds an event listener for when the terminal is resized. The event value + * contains the new size. + * @returns an `IDisposable` to stop listening. + */ + onResize: IEvent<{ cols: number, rows: number }>; + + /** + * Adds an event listener for when an OSC 0 or OSC 2 title change occurs. + * The event value is the new title. + * @returns an `IDisposable` to stop listening. + */ + onTitleChange: IEvent; + /** * Unfocus the terminal. */ @@ -371,97 +473,14 @@ declare module 'vscode-xterm' { focus(): void; /** - * Registers an event listener. - * @param type The type of the event. - * @param listener The listener. - */ - on(type: 'blur' | 'focus' | 'linefeed' | 'selection', listener: () => void): void; - /** - * Registers an event listener. - * @param type The type of the event. - * @param listener The listener. - */ - on(type: 'data', listener: (...args: any[]) => void): void; - /** - * Registers an event listener. - * @param type The type of the event. - * @param listener The listener. - */ - on(type: 'key', listener: (key: string, event: KeyboardEvent) => void): void; - /** - * Registers an event listener. - * @param type The type of the event. - * @param listener The listener. - */ - on(type: 'keypress' | 'keydown', listener: (event: KeyboardEvent) => void): void; - /** - * Registers an event listener. - * @param type The type of the event. - * @param listener The listener. - */ - on(type: 'refresh', listener: (data: { start: number, end: number }) => void): void; - /** - * Registers an event listener. - * @param type The type of the event. - * @param listener The listener. - */ - on(type: 'resize', listener: (data: { cols: number, rows: number }) => void): void; - /** - * Registers an event listener. - * @param type The type of the event. - * @param listener The listener. - */ - on(type: 'scroll', listener: (ydisp: number) => void): void; - /** - * Registers an event listener. - * @param type The type of the event. - * @param listener The listener. - */ - on(type: 'title', listener: (title: string) => void): void; - /** - * Registers an event listener. - * @param type The type of the event. - * @param listener The listener. - */ - on(type: string, listener: (...args: any[]) => void): void; - - /** - * Deregisters an event listener. - * @param type The type of the event. - * @param listener The listener. - */ - off(type: 'blur' | 'focus' | 'linefeed' | 'selection' | 'data' | 'key' | 'keypress' | 'keydown' | 'refresh' | 'resize' | 'scroll' | 'title' | string, listener: (...args: any[]) => void): void; - - /** - * Emits an event on the terminal. - * @param type The type of event - * @param data data associated with the event. - * @deprecated This is being removed from the API with no replacement, see - * issue #1505. - */ - emit(type: string, data?: any): void; - - /** - * Adds an event listener to the Terminal, returning an IDisposable that can - * be used to conveniently remove the event listener. - * @param type The type of event. - * @param handler The event handler. - */ - addDisposableListener(type: string, handler: (...args: any[]) => void): IDisposable; - - /** - * Resizes the terminal. + * Resizes the terminal. It's best practice to debounce calls to resize, + * this will help ensure that the pty can respond to the resize event + * before another one occurs. * @param x The number of columns to resize to. * @param y The number of rows to resize to. */ resize(columns: number, rows: number): void; - /** - * Writes text to the terminal, followed by a break line character (\n). - * @param data The text to write to the terminal. - */ - writeln(data: string): void; - /** * Opens the terminal within an element. * @param parent The element to create the terminal within. This element @@ -476,11 +495,37 @@ declare module 'vscode-xterm' { * should be processed by the terminal and what keys should not. * @param customKeyEventHandler The custom KeyboardEvent handler to attach. * This is a function that takes a KeyboardEvent, allowing consumers to stop - * propogation and/or prevent the default action. The function returns + * propagation and/or prevent the default action. The function returns * whether the event should be processed by xterm.js. */ attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void; + /** + * (EXPERIMENTAL) Adds a handler for CSI escape sequences. + * @param flag The flag should be one-character string, which specifies the + * final character (e.g "m" for SGR) of the CSI sequence. + * @param callback The function to handle the escape sequence. The callback + * is called with the numerical params, as well as the special characters + * (e.g. "$" for DECSCPP). If the sequence has subparams the array will + * contain subarrays with their numercial values. + * Return true if the sequence was handled; false if + * we should try a previous handler (set by addCsiHandler or setCsiHandler). + * The most recently-added handler is tried first. + * @return An IDisposable you can call to remove this handler. + */ + addCsiHandler(flag: string, callback: (params: (number | number[])[], collect: string) => boolean): IDisposable; + + /** + * (EXPERIMENTAL) Adds a handler for OSC escape sequences. + * @param ident The number (first parameter) of the sequence. + * @param callback The function to handle the escape sequence. The callback + * is called with OSC data string. Return true if the sequence was handled; + * false if we should try a previous handler (set by addOscHandler or + * setOscHandler). The most recently-added handler is tried first. + * @return An IDisposable you can call to remove this handler. + */ + addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable; + /** * (EXPERIMENTAL) Registers a link matcher, allowing custom link patterns to * be matched and handled. @@ -555,11 +600,24 @@ declare module 'vscode-xterm' { */ getSelection(): string; + /** + * Gets the selection position or undefined if there is no selection. + */ + getSelectionPosition(): ISelectionPosition | undefined; + /** * Clears the current terminal selection. */ clearSelection(): void; + /** + * Selects text within the terminal. + * @param column The column the selection starts at.. + * @param row The row the selection starts at. + * @param length The length of the selection. + */ + select(column: number, row: number, length: number): void; + /** * Selects all text within the terminal. */ @@ -578,13 +636,6 @@ declare module 'vscode-xterm' { */ dispose(): void; - /** - * Destroys the terminal and detaches it from the DOM. - * - * @deprecated Use dispose() instead. - */ - destroy(): void; - /** * Scroll the display of the terminal * @param amount The number of lines to scroll down (negative scroll up). @@ -625,15 +676,29 @@ declare module 'vscode-xterm' { write(data: string): void; /** - * Retrieves an option's value from the terminal. - * @param key The option key. + * Writes text to the terminal, followed by a break line character (\n). + * @param data The text to write to the terminal. */ - getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'rendererType' | 'termName'): string; + writeln(data: string): void; + + /** + * Writes UTF8 data to the terminal. This has a slight performance advantage + * over the string based write method due to lesser data conversions needed + * on the way from the pty to xterm.js. + * @param data The data to write to the terminal. + */ + writeUtf8(data: Uint8Array): void; + /** * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; + getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string; + /** + * Retrieves an option's value from the terminal. + * @param key The option key. + */ + getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode'): boolean; /** * Retrieves an option's value from the terminal. * @param key The option key. @@ -660,13 +725,19 @@ declare module 'vscode-xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: 'fontFamily' | 'termName' | 'bellSound', value: string): void; + setOption(key: 'fontFamily' | 'termName' | 'bellSound' | 'wordSeparator', value: string): void; /** * Sets an option on the terminal. * @param key The option key. * @param value The option value. */ setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'logLevel', value: LogLevel): void; /** * Sets an option on the terminal. * @param key The option key. @@ -684,7 +755,7 @@ declare module 'vscode-xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'popOnBell' | 'rightClickSelectsWord' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void; + setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'popOnBell' | 'rightClickSelectsWord' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode', value: boolean): void; /** * Sets an option on the terminal. * @param key The option key. @@ -739,79 +810,181 @@ declare module 'vscode-xterm' { * Applies an addon to the Terminal prototype, making it available to all * newly created Terminals. * @param addon The addon to apply. + * @deprecated Use the new loadAddon API/addon format. */ static applyAddon(addon: any): void; + + /** + * (EXPERIMENTAL) Loads an addon into this instance of xterm.js. + * @param addon The addon to load. + */ + loadAddon(addon: ITerminalAddon): void; + } + + /** + * An addon that can provide additional functionality to the terminal. + */ + export interface ITerminalAddon extends IDisposable { + /** + * (EXPERIMENTAL) This is called when the addon is activated. + */ + activate(terminal: Terminal): void; + } + + /** + * An object representing a selection within the terminal. + */ + interface ISelectionPosition { + /** + * The start column of the selection. + */ + startColumn: number; + + /** + * The start row of the selection. + */ + startRow: number; + + /** + * The end column of the selection. + */ + endColumn: number; + + /** + * The end row of the selection. + */ + endRow: number; + } + + /** + * Represents a terminal buffer. + */ + interface IBuffer { + /** + * The y position of the cursor. This ranges between `0` (when the + * cursor is at baseY) and `Terminal.rows - 1` (when the cursor is on the + * last row). + */ + readonly cursorY: number; + + /** + * The x position of the cursor. This ranges between `0` (left side) and + * `Terminal.cols - 1` (right side). + */ + readonly cursorX: number; + + /** + * The line within the buffer where the top of the viewport is. + */ + readonly viewportY: number; + + /** + * The line within the buffer where the top of the bottom page is (when + * fully scrolled down); + */ + readonly baseY: number; + + /** + * The amount of lines in the buffer. + */ + readonly length: number; + + /** + * Gets a line from the buffer, or undefined if the line index does not + * exist. + * + * Note that the result of this function should be used immediately after + * calling as when the terminal updates it could lead to unexpected + * behavior. + * + * @param y The line index to get. + */ + getLine(y: number): IBufferLine | undefined; + } + + /** + * Represents a line in the terminal's buffer. + */ + interface IBufferLine { + /** + * Whether the line is wrapped from the previous line. + */ + readonly isWrapped: boolean; + + /** + * Gets a cell from the line, or undefined if the line index does not exist. + * + * Note that the result of this function should be used immediately after + * calling as when the terminal updates it could lead to unexpected + * behavior. + * + * @param x The character index to get. + */ + getCell(x: number): IBufferCell | undefined; + + /** + * Gets the line as a string. Note that this is gets only the string for the + * line, not taking isWrapped into account. + * + * @param trimRight Whether to trim any whitespace at the right of the line. + * @param startColumn The column to start from (inclusive). + * @param endColumn The column to end at (exclusive). + */ + translateToString(trimRight?: boolean, startColumn?: number, endColumn?: number): string; + } + + /** + * Represents a single cell in the terminal's buffer. + */ + interface IBufferCell { + /** + * The character within the cell. + */ + readonly char: string; + + /** + * The width of the character. Some examples: + * + * - This is `1` for most cells. + * - This is `2` for wide character like CJK glyphs. + * - This is `0` for cells immediately following cells with a width of `2`. + */ + readonly width: number; } } + + + // Modifications to official .d.ts below -declare module 'vscode-xterm' { +declare module 'xterm' { interface TerminalCore { - debug: boolean; + _onScroll: IEventEmitter; + _onKey: IEventEmitter<{ key: string }>; - buffer: { - y: number; - ybase: number; - ydisp: number; - x: number; - lines: any[]; - - translateBufferLineToString(lineIndex: number, trimRight: boolean): string; + _charSizeService: { + width: number; + height: number; }; - handler(text: string): void; + _coreService: { + triggerDataEvent(data: string, wasUserInput?: boolean): void; + } - /** - * Emit an event on the terminal. - */ - emit(type: string, data: any): void; - - charMeasure?: { height: number, width: number }; - - renderer: { - _renderLayers: any[]; - onIntersectionChange: any; + _renderService: { + _renderer: { + _renderLayers: any[]; + }; + _onIntersectionChange: any; }; } - interface ISearchOptions { - /** - * Whether the find should be done as a regex. - */ - regex?: boolean; - /** - * Whether only whole words should match. - */ - wholeWord?: boolean; - /** - * Whether find should pay attention to case. - */ - caseSensitive?: boolean; + interface IEventEmitter { + fire(e: T): void; } interface Terminal { _core: TerminalCore; - - webLinksInit(handler?: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): void; - winptyCompatInit(): void; - - /** - * Find the next instance of the term, then scroll to and select it. If it - * doesn't exist, do nothing. - * @param term The search term. - * @param findOptions Regex, whole word, and case sensitive options. - * @return Whether a result was found. - */ - findNext(term: string, findOptions: ISearchOptions): boolean; - - /** - * Find the previous instance of the term, then scroll to and select it. If it - * doesn't exist, do nothing. - * @param term The search term. - * @param findOptions Regex, whole word, and case sensitive options. - * @return Whether a result was found. - */ - findPrevious(term: string, findOptions: ISearchOptions): boolean; } -} +} \ No newline at end of file diff --git a/src/typings/yauzl.d.ts b/src/typings/yauzl.d.ts index 3295c92ecb9..39ef2ad9488 100644 --- a/src/typings/yauzl.d.ts +++ b/src/typings/yauzl.d.ts @@ -31,18 +31,19 @@ declare module 'yauzl' { } export class ZipFile extends EventEmitter { - readEntry(); - openReadStream(entry: Entry, callback: (err?: Error, stream?: Readable) => void); - close(); + readEntry(): void; + openReadStream(entry: Entry, callback: (err?: Error, stream?: Readable) => void): void; + close(): void; isOpen: boolean; entryCount: number; comment: string; } export interface IOptions { - autoClose: boolean; + autoClose?: boolean; + lazyEntries?: boolean; } export function open(path: string, callback: (err?: Error, zipfile?: ZipFile) => void): void; - export function open(path: string, options: IOptions, callback: (err?: Error, zipfile?: ZipFile) => void): void; + export function open(path: string, options: IOptions | undefined, callback: (err?: Error, zipfile?: ZipFile) => void): void; } \ No newline at end of file diff --git a/src/typings/yazl.d.ts b/src/typings/yazl.d.ts index 0aa227a6c82..5644d092913 100644 --- a/src/typings/yazl.d.ts +++ b/src/typings/yazl.d.ts @@ -8,8 +8,8 @@ declare module 'yazl' { class ZipFile { outputStream: stream.Stream; - addBuffer(buffer: Buffer, path: string); - addFile(localPath: string, path: string); - end(); + addBuffer(buffer: Buffer, path: string): void; + addFile(localPath: string, path: string): void; + end(): void; } } \ No newline at end of file diff --git a/src/vs/base/browser/browser.ts b/src/vs/base/browser/browser.ts index e687780e57c..1641b7304af 100644 --- a/src/vs/base/browser/browser.ts +++ b/src/vs/base/browser/browser.ts @@ -5,7 +5,6 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; -import * as platform from 'vs/base/common/platform'; class WindowManager { @@ -35,7 +34,7 @@ class WindowManager { } // --- Zoom Factor - private _zoomFactor: number = 0; + private _zoomFactor: number = 1; public getZoomFactor(): number { return this._zoomFactor; @@ -46,18 +45,18 @@ class WindowManager { // --- Pixel Ratio public getPixelRatio(): number { - let ctx = document.createElement('canvas').getContext('2d'); + let ctx: any = document.createElement('canvas').getContext('2d'); let dpr = window.devicePixelRatio || 1; - let bsr = (ctx).webkitBackingStorePixelRatio || - (ctx).mozBackingStorePixelRatio || - (ctx).msBackingStorePixelRatio || - (ctx).oBackingStorePixelRatio || - (ctx).backingStorePixelRatio || 1; + let bsr = ctx.webkitBackingStorePixelRatio || + ctx.mozBackingStorePixelRatio || + ctx.msBackingStorePixelRatio || + ctx.oBackingStorePixelRatio || + ctx.backingStorePixelRatio || 1; return dpr / bsr; } // --- Fullscreen - private _fullscreen: boolean; + private _fullscreen: boolean = false; private readonly _onDidChangeFullscreen = new Emitter(); public readonly onDidChangeFullscreen: Event = this._onDidChangeFullscreen.event; @@ -72,23 +71,6 @@ class WindowManager { public isFullscreen(): boolean { return this._fullscreen; } - - // --- Accessibility - private _accessibilitySupport = platform.AccessibilitySupport.Unknown; - private readonly _onDidChangeAccessibilitySupport = new Emitter(); - - public readonly onDidChangeAccessibilitySupport: Event = this._onDidChangeAccessibilitySupport.event; - public setAccessibilitySupport(accessibilitySupport: platform.AccessibilitySupport): void { - if (this._accessibilitySupport === accessibilitySupport) { - return; - } - - this._accessibilitySupport = accessibilitySupport; - this._onDidChangeAccessibilitySupport.fire(); - } - public getAccessibilitySupport(): platform.AccessibilitySupport { - return this._accessibilitySupport; - } } /** A zoom index, e.g. 1, 2, 3 */ @@ -126,16 +108,6 @@ export function isFullscreen(): boolean { } export const onDidChangeFullscreen = WindowManager.INSTANCE.onDidChangeFullscreen; -export function setAccessibilitySupport(accessibilitySupport: platform.AccessibilitySupport): void { - WindowManager.INSTANCE.setAccessibilitySupport(accessibilitySupport); -} -export function getAccessibilitySupport(): platform.AccessibilitySupport { - return WindowManager.INSTANCE.getAccessibilitySupport(); -} -export function onDidChangeAccessibilitySupport(callback: () => void): IDisposable { - return WindowManager.INSTANCE.onDidChangeAccessibilitySupport(callback); -} - const userAgent = navigator.userAgent; export const isIE = (userAgent.indexOf('Trident') >= 0); @@ -146,9 +118,11 @@ export const isOpera = (userAgent.indexOf('Opera') >= 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 = (userAgent.indexOf('Chrome') === -1) && (userAgent.indexOf('Safari') >= 0); +export const isSafari = (!isChrome && (userAgent.indexOf('Safari') >= 0)); +export const isWebkitWebView = (!isChrome && !isSafari && isWebKit); export const isIPad = (userAgent.indexOf('iPad') >= 0); export const isEdgeWebView = isEdge && (userAgent.indexOf('WebView/') >= 0); +export const isStandalone = (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches); export function hasClipboardSupport() { if (isIE) { diff --git a/src/vs/base/browser/contextmenu.ts b/src/vs/base/browser/contextmenu.ts index 98a5c02d180..54dc4d766ca 100644 --- a/src/vs/base/browser/contextmenu.ts +++ b/src/vs/base/browser/contextmenu.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IAction, IActionRunner } from 'vs/base/common/actions'; -import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; +import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; import { SubmenuAction } from 'vs/base/browser/ui/menu/menu'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; @@ -24,10 +24,10 @@ export class ContextSubMenu extends SubmenuAction { export interface IContextMenuDelegate { getAnchor(): HTMLElement | { x: number; y: number; width?: number; height?: number; }; - getActions(): Array; - getActionItem?(action: IAction): IActionItem | null; + getActions(): ReadonlyArray; + getActionViewItem?(action: IAction): IActionViewItem | undefined; getActionsContext?(event?: IContextMenuEvent): any; - getKeyBinding?(action: IAction): ResolvedKeybinding | null; + getKeyBinding?(action: IAction): ResolvedKeybinding | undefined; getMenuClassName?(): string; onHide?(didCancel: boolean): void; actionRunner?: IActionRunner; diff --git a/src/vs/base/browser/dnd.ts b/src/vs/base/browser/dnd.ts index a51f6e64b8e..1a5d28e802e 100644 --- a/src/vs/base/browser/dnd.ts +++ b/src/vs/base/browser/dnd.ts @@ -16,7 +16,9 @@ export class DelayedDragHandler extends Disposable { constructor(container: HTMLElement, callback: () => void) { super(); - this._register(addDisposableListener(container, 'dragover', () => { + this._register(addDisposableListener(container, 'dragover', e => { + e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome) + if (!this.timeout) { this.timeout = setTimeout(() => { callback(); @@ -27,7 +29,7 @@ export class DelayedDragHandler extends Disposable { })); ['dragleave', 'drop', 'dragend'].forEach(type => { - this._register(addDisposableListener(container, type as 'dragleave' | 'drop' | 'dragend', () => { + this._register(addDisposableListener(container, type, () => { this.clearDragTimeout(); })); }); @@ -66,12 +68,12 @@ export const DataTransfers = { FILES: 'Files', /** - * Typicaly transfer type for copy/paste transfers. + * Typically transfer type for copy/paste transfers. */ TEXT: 'text/plain' }; -export function applyDragImage(event: DragEvent, label: string, clazz: string): void { +export function applyDragImage(event: DragEvent, label: string | null, clazz: string): void { const dragImage = document.createElement('div'); dragImage.className = clazz; dragImage.textContent = label; @@ -83,4 +85,30 @@ export function applyDragImage(event: DragEvent, label: string, clazz: string): // Removes the element when the DND operation is done setTimeout(() => document.body.removeChild(dragImage), 0); } -} \ No newline at end of file +} + +export interface IDragAndDropData { + update(dataTransfer: DataTransfer): void; + getData(): any; +} + +export class DragAndDropData implements IDragAndDropData { + + constructor(private data: T) { } + + update(): void { + // noop + } + + getData(): T { + return this.data; + } +} + +export interface IStaticDND { + CurrentDragAndDropData: IDragAndDropData | undefined; +} + +export const StaticDND: IStaticDND = { + CurrentDragAndDropData: undefined +}; \ No newline at end of file diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index d765620746f..717041747da 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -11,9 +11,11 @@ import { TimeoutTimer } from 'vs/base/common/async'; import { CharCode } from 'vs/base/common/charCode'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; -import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import * as platform from 'vs/base/common/platform'; import { coalesce } from 'vs/base/common/arrays'; +import { URI } from 'vs/base/common/uri'; +import { Schemas } from 'vs/base/common/network'; export function clearNode(node: HTMLElement): void { while (node.firstChild) { @@ -32,24 +34,24 @@ export function isInDOM(node: Node | null): boolean { if (node === document.body) { return true; } - node = node.parentNode; + node = node.parentNode || (node as ShadowRoot).host; } return false; } interface IDomClassList { - hasClass(node: HTMLElement, className: string): boolean; - addClass(node: HTMLElement, className: string): void; - addClasses(node: HTMLElement, ...classNames: string[]): void; - removeClass(node: HTMLElement, className: string): void; - removeClasses(node: HTMLElement, ...classNames: string[]): void; - toggleClass(node: HTMLElement, className: string, shouldHaveIt?: boolean): void; + hasClass(node: HTMLElement | SVGElement, className: string): boolean; + addClass(node: HTMLElement | SVGElement, className: string): void; + addClasses(node: HTMLElement | SVGElement, ...classNames: string[]): void; + removeClass(node: HTMLElement | SVGElement, className: string): void; + removeClasses(node: HTMLElement | SVGElement, ...classNames: string[]): void; + toggleClass(node: HTMLElement | SVGElement, className: string, shouldHaveIt?: boolean): void; } const _manualClassList = new class implements IDomClassList { - private _lastStart: number; - private _lastEnd: number; + private _lastStart: number = -1; + private _lastEnd: number = -1; private _findClassName(node: HTMLElement, className: string): void { @@ -191,12 +193,12 @@ const _nativeClassList = new class implements IDomClassList { // In IE11 there is only partial support for `classList` which makes us keep our // custom implementation. Otherwise use the native implementation, see: http://caniuse.com/#search=classlist const _classList: IDomClassList = browser.isIE ? _manualClassList : _nativeClassList; -export const hasClass: (node: HTMLElement, className: string) => boolean = _classList.hasClass.bind(_classList); -export const addClass: (node: HTMLElement, className: string) => void = _classList.addClass.bind(_classList); -export const addClasses: (node: HTMLElement, ...classNames: string[]) => void = _classList.addClasses.bind(_classList); -export const removeClass: (node: HTMLElement, className: string) => void = _classList.removeClass.bind(_classList); -export const removeClasses: (node: HTMLElement, ...classNames: string[]) => void = _classList.removeClasses.bind(_classList); -export const toggleClass: (node: HTMLElement, className: string, shouldHaveIt?: boolean) => void = _classList.toggleClass.bind(_classList); +export const hasClass: (node: HTMLElement | SVGElement, className: string) => boolean = _classList.hasClass.bind(_classList); +export const addClass: (node: HTMLElement | SVGElement, className: string) => void = _classList.addClass.bind(_classList); +export const addClasses: (node: HTMLElement | SVGElement, ...classNames: string[]) => void = _classList.addClasses.bind(_classList); +export const removeClass: (node: HTMLElement | SVGElement, className: string) => void = _classList.removeClass.bind(_classList); +export const removeClasses: (node: HTMLElement | SVGElement, ...classNames: string[]) => void = _classList.removeClasses.bind(_classList); +export const toggleClass: (node: HTMLElement | SVGElement, className: string, shouldHaveIt?: boolean) => void = _classList.toggleClass.bind(_classList); class DomListener implements IDisposable { @@ -467,28 +469,6 @@ export function getComputedStyle(el: HTMLElement): CSSStyleDeclaration { return document.defaultView!.getComputedStyle(el, null); } -// Adapted from WinJS -// Converts a CSS positioning string for the specified element to pixels. -const convertToPixels: (element: HTMLElement, value: string) => number = (function () { - return function (element: HTMLElement, value: string): number { - return parseFloat(value) || 0; - }; -})(); - -function getDimension(element: HTMLElement, cssPropertyName: string, jsPropertyName: string): number { - let computedStyle: CSSStyleDeclaration = getComputedStyle(element); - let value = '0'; - if (computedStyle) { - if (computedStyle.getPropertyValue) { - value = computedStyle.getPropertyValue(cssPropertyName); - } else { - // IE8 - value = (computedStyle).getAttribute(jsPropertyName); - } - } - return convertToPixels(element, value); -} - export function getClientArea(element: HTMLElement): Dimension { // Try with DOM clientWidth / clientHeight @@ -514,48 +494,66 @@ export function getClientArea(element: HTMLElement): Dimension { throw new Error('Unable to figure out browser width and height'); } -const sizeUtils = { +class SizeUtils { + // Adapted from WinJS + // Converts a CSS positioning string for the specified element to pixels. + private static convertToPixels(element: HTMLElement, value: string): number { + return parseFloat(value) || 0; + } - getBorderLeftWidth: function (element: HTMLElement): number { - return getDimension(element, 'border-left-width', 'borderLeftWidth'); - }, - getBorderRightWidth: function (element: HTMLElement): number { - return getDimension(element, 'border-right-width', 'borderRightWidth'); - }, - getBorderTopWidth: function (element: HTMLElement): number { - return getDimension(element, 'border-top-width', 'borderTopWidth'); - }, - getBorderBottomWidth: function (element: HTMLElement): number { - return getDimension(element, 'border-bottom-width', 'borderBottomWidth'); - }, + private static getDimension(element: HTMLElement, cssPropertyName: string, jsPropertyName: string): number { + let computedStyle: CSSStyleDeclaration = getComputedStyle(element); + let value = '0'; + if (computedStyle) { + if (computedStyle.getPropertyValue) { + value = computedStyle.getPropertyValue(cssPropertyName); + } else { + // IE8 + value = (computedStyle).getAttribute(jsPropertyName); + } + } + return SizeUtils.convertToPixels(element, value); + } - getPaddingLeft: function (element: HTMLElement): number { - return getDimension(element, 'padding-left', 'paddingLeft'); - }, - getPaddingRight: function (element: HTMLElement): number { - return getDimension(element, 'padding-right', 'paddingRight'); - }, - getPaddingTop: function (element: HTMLElement): number { - return getDimension(element, 'padding-top', 'paddingTop'); - }, - getPaddingBottom: function (element: HTMLElement): number { - return getDimension(element, 'padding-bottom', 'paddingBottom'); - }, + static getBorderLeftWidth(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'border-left-width', 'borderLeftWidth'); + } + static getBorderRightWidth(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'border-right-width', 'borderRightWidth'); + } + static getBorderTopWidth(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'border-top-width', 'borderTopWidth'); + } + static getBorderBottomWidth(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'border-bottom-width', 'borderBottomWidth'); + } - getMarginLeft: function (element: HTMLElement): number { - return getDimension(element, 'margin-left', 'marginLeft'); - }, - getMarginTop: function (element: HTMLElement): number { - return getDimension(element, 'margin-top', 'marginTop'); - }, - getMarginRight: function (element: HTMLElement): number { - return getDimension(element, 'margin-right', 'marginRight'); - }, - getMarginBottom: function (element: HTMLElement): number { - return getDimension(element, 'margin-bottom', 'marginBottom'); - }, - __commaSentinel: false -}; + static getPaddingLeft(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'padding-left', 'paddingLeft'); + } + static getPaddingRight(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'padding-right', 'paddingRight'); + } + static getPaddingTop(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'padding-top', 'paddingTop'); + } + static getPaddingBottom(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'padding-bottom', 'paddingBottom'); + } + + static getMarginLeft(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'margin-left', 'marginLeft'); + } + static getMarginTop(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'margin-top', 'marginTop'); + } + static getMarginRight(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'margin-right', 'marginRight'); + } + static getMarginBottom(element: HTMLElement): number { + return SizeUtils.getDimension(element, 'margin-bottom', 'marginBottom'); + } +} // ---------------------------------------------------------------------------------------- // Position & Dimension @@ -594,8 +592,8 @@ export function getTopLeftOffset(element: HTMLElement): { left: number; top: num } if (element === offsetParent) { - left += sizeUtils.getBorderLeftWidth(element); - top += sizeUtils.getBorderTopWidth(element); + left += SizeUtils.getBorderLeftWidth(element); + top += SizeUtils.getBorderTopWidth(element); top += element.offsetTop; left += element.offsetLeft; offsetParent = element.offsetParent; @@ -615,7 +613,7 @@ export interface IDomNodePagePosition { height: number; } -export function size(element: HTMLElement, width: number, height: number): void { +export function size(element: HTMLElement, width: number | null, height: number | null): void { if (typeof width === 'number') { element.style.width = `${width}px`; } @@ -686,33 +684,33 @@ export const StandardWindow: IStandardWindow = new class implements IStandardWin // Adapted from WinJS // Gets the width of the element, including margins. export function getTotalWidth(element: HTMLElement): number { - let margin = sizeUtils.getMarginLeft(element) + sizeUtils.getMarginRight(element); + let margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element); return element.offsetWidth + margin; } export function getContentWidth(element: HTMLElement): number { - let border = sizeUtils.getBorderLeftWidth(element) + sizeUtils.getBorderRightWidth(element); - let padding = sizeUtils.getPaddingLeft(element) + sizeUtils.getPaddingRight(element); + let border = SizeUtils.getBorderLeftWidth(element) + SizeUtils.getBorderRightWidth(element); + let padding = SizeUtils.getPaddingLeft(element) + SizeUtils.getPaddingRight(element); return element.offsetWidth - border - padding; } export function getTotalScrollWidth(element: HTMLElement): number { - let margin = sizeUtils.getMarginLeft(element) + sizeUtils.getMarginRight(element); + let margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element); return element.scrollWidth + margin; } // Adapted from WinJS // Gets the height of the content of the specified element. The content height does not include borders or padding. export function getContentHeight(element: HTMLElement): number { - let border = sizeUtils.getBorderTopWidth(element) + sizeUtils.getBorderBottomWidth(element); - let padding = sizeUtils.getPaddingTop(element) + sizeUtils.getPaddingBottom(element); + let border = SizeUtils.getBorderTopWidth(element) + SizeUtils.getBorderBottomWidth(element); + let padding = SizeUtils.getPaddingTop(element) + SizeUtils.getPaddingBottom(element); return element.offsetHeight - border - padding; } // Adapted from WinJS // Gets the height of the element, including its margins. export function getTotalHeight(element: HTMLElement): number { - let margin = sizeUtils.getMarginTop(element) + sizeUtils.getMarginBottom(element); + let margin = SizeUtils.getMarginTop(element) + SizeUtils.getMarginBottom(element); return element.offsetHeight + margin; } @@ -772,6 +770,10 @@ export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClaz return null; } +export function hasParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): boolean { + return !!findParentWithClass(node, clazz, stopAtClazzOrNode); +} + export function createStyleSheet(container: HTMLElement = document.getElementsByTagName('head')[0]): HTMLStyleElement { let style = document.createElement('style'); style.type = 'text/css'; @@ -836,53 +838,55 @@ export function isHTMLElement(o: any): o is HTMLElement { export const EventType = { // Mouse - CLICK: 'click' as 'click', - DBLCLICK: 'dblclick' as 'dblclick', - MOUSE_UP: 'mouseup' as 'mouseup', - MOUSE_DOWN: 'mousedown' as 'mousedown', - MOUSE_OVER: 'mouseover' as 'mouseover', - MOUSE_MOVE: 'mousemove' as 'mousemove', - MOUSE_OUT: 'mouseout' as 'mouseout', - MOUSE_ENTER: 'mouseenter' as 'mouseenter', - MOUSE_LEAVE: 'mouseleave' as 'mouseleave', - CONTEXT_MENU: 'contextmenu' as 'contextmenu', - WHEEL: 'wheel' as 'wheel', + CLICK: 'click', + DBLCLICK: 'dblclick', + MOUSE_UP: 'mouseup', + MOUSE_DOWN: 'mousedown', + MOUSE_OVER: 'mouseover', + MOUSE_MOVE: 'mousemove', + MOUSE_OUT: 'mouseout', + MOUSE_ENTER: 'mouseenter', + MOUSE_LEAVE: 'mouseleave', + CONTEXT_MENU: 'contextmenu', + WHEEL: 'wheel', // Keyboard - KEY_DOWN: 'keydown' as 'keydown', - KEY_PRESS: 'keypress' as 'keypress', - KEY_UP: 'keyup' as 'keyup', + KEY_DOWN: 'keydown', + KEY_PRESS: 'keypress', + KEY_UP: 'keyup', // HTML Document - LOAD: 'load' as 'load', - UNLOAD: 'unload' as 'unload', - ABORT: 'abort' as 'abort', - ERROR: 'error' as 'error', - RESIZE: 'resize' as 'resize', - SCROLL: 'scroll' as 'scroll', + LOAD: 'load', + UNLOAD: 'unload', + ABORT: 'abort', + ERROR: 'error', + RESIZE: 'resize', + SCROLL: 'scroll', + FULLSCREEN_CHANGE: 'fullscreenchange', + WK_FULLSCREEN_CHANGE: 'webkitfullscreenchange', // Form - SELECT: 'select' as 'select', - CHANGE: 'change' as 'change', - SUBMIT: 'submit' as 'submit', - RESET: 'reset' as 'reset', - FOCUS: 'focus' as 'focus', - FOCUS_IN: 'focusin' as 'focusin', - FOCUS_OUT: 'focusout' as 'focusout', - BLUR: 'blur' as 'blur', - INPUT: 'input' as 'input', + SELECT: 'select', + CHANGE: 'change', + SUBMIT: 'submit', + RESET: 'reset', + FOCUS: 'focus', + FOCUS_IN: 'focusin', + FOCUS_OUT: 'focusout', + BLUR: 'blur', + INPUT: 'input', // Local Storage - STORAGE: 'storage' as 'storage', + STORAGE: 'storage', // Drag - DRAG_START: 'dragstart' as 'dragstart', - DRAG: 'drag' as 'drag', - DRAG_ENTER: 'dragenter' as 'dragenter', - DRAG_LEAVE: 'dragleave' as 'dragleave', - DRAG_OVER: 'dragover' as 'dragover', - DROP: 'drop' as 'drop', - DRAG_END: 'dragend' as 'dragend', + DRAG_START: 'dragstart', + DRAG: 'drag', + DRAG_ENTER: 'dragenter', + DRAG_LEAVE: 'dragleave', + DRAG_OVER: 'dragover', + DROP: 'drop', + DRAG_END: 'dragend', // Animation ANIMATION_START: browser.isWebKit ? 'webkitAnimationStart' : 'animationstart', ANIMATION_END: browser.isWebKit ? 'webkitAnimationEnd' : 'animationend', ANIMATION_ITERATION: browser.isWebKit ? 'webkitAnimationIteration' : 'animationiteration' -}; +} as const; export interface EventLike { preventDefault(): void; @@ -909,10 +913,9 @@ export const EventHelper = { } }; -export interface IFocusTracker { +export interface IFocusTracker extends Disposable { onDidFocus: Event; onDidBlur: Event; - dispose(): void; } export function saveParentsScrollTop(node: Element): number[] { @@ -933,21 +936,20 @@ export function restoreParentsScrollTop(node: Element, state: number[]): void { } } -class FocusTracker implements IFocusTracker { +class FocusTracker extends Disposable implements IFocusTracker { - private _onDidFocus = new Emitter(); - readonly onDidFocus: Event = this._onDidFocus.event; + private readonly _onDidFocus = this._register(new Emitter()); + public readonly onDidFocus: Event = this._onDidFocus.event; - private _onDidBlur = new Emitter(); - readonly onDidBlur: Event = this._onDidBlur.event; - - private disposables: IDisposable[] = []; + private readonly _onDidBlur = this._register(new Emitter()); + public readonly onDidBlur: Event = this._onDidBlur.event; constructor(element: HTMLElement | Window) { + super(); let hasFocus = isAncestor(document.activeElement, element); let loosingFocus = false; - let onFocus = () => { + const onFocus = () => { loosingFocus = false; if (!hasFocus) { hasFocus = true; @@ -955,7 +957,7 @@ class FocusTracker implements IFocusTracker { } }; - let onBlur = () => { + const onBlur = () => { if (hasFocus) { loosingFocus = true; window.setTimeout(() => { @@ -968,14 +970,8 @@ class FocusTracker implements IFocusTracker { } }; - domEvent(element, EventType.FOCUS, true)(onFocus, null, this.disposables); - domEvent(element, EventType.BLUR, true)(onBlur, null, this.disposables); - } - - dispose(): void { - this.disposables = dispose(this.disposables); - this._onDidFocus.dispose(); - this._onDidBlur.dispose(); + this._register(domEvent(element, EventType.FOCUS, true)(onFocus)); + this._register(domEvent(element, EventType.BLUR, true)(onBlur)); } } @@ -995,14 +991,28 @@ export function prepend(parent: HTMLElement, child: T): T { const SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((.([\w\-]+))*)/; -export function $(description: string, attrs?: { [key: string]: any; }, ...children: Array): T { +export enum Namespace { + HTML = 'http://www.w3.org/1999/xhtml', + SVG = 'http://www.w3.org/2000/svg' +} + +function _$(namespace: Namespace, description: string, attrs?: { [key: string]: any; }, ...children: Array): T { let match = SELECTOR_REGEX.exec(description); if (!match) { throw new Error('Bad use of emmet'); } - let result = document.createElement(match[1] || 'div'); + attrs = { ...(attrs || {}) }; + + let tagName = match[1] || 'div'; + let result: T; + + if (namespace !== Namespace.HTML) { + result = document.createElementNS(namespace as string, tagName) as T; + } else { + result = document.createElement(tagName) as unknown as T; + } if (match[3]) { result.id = match[3]; @@ -1011,7 +1021,6 @@ export function $(description: string, attrs?: { [key: st result.className = match[4].replace(/\./g, ' ').trim(); } - attrs = attrs || {}; Object.keys(attrs).forEach(name => { const value = attrs![name]; if (/^on\w+$/.test(name)) { @@ -1038,6 +1047,14 @@ export function $(description: string, attrs?: { [key: st return result as T; } +export function $(description: string, attrs?: { [key: string]: any; }, ...children: Array): T { + return _$(Namespace.HTML, description, attrs, ...children); +} + +$.SVG = function (description: string, attrs?: { [key: string]: any; }, ...children: Array): T { + return _$(Namespace.SVG, description, attrs, ...children); +}; + export function join(nodes: Node[], separator: Node | string): Node[] { const result: Node[] = []; @@ -1157,3 +1174,33 @@ export function windowOpenNoOpener(url: string): void { } } } + +export function animate(fn: () => void): IDisposable { + const step = () => { + fn(); + stepDisposable = scheduleAtNextAnimationFrame(step); + }; + + let stepDisposable = scheduleAtNextAnimationFrame(step); + return toDisposable(() => stepDisposable.dispose()); +} + + + +const _location = URI.parse(window.location.href); + +export function asDomUri(uri: URI): URI { + if (!uri) { + return uri; + } + if (!platform.isWeb) { + //todo@joh remove this once we have sw in electron going + return uri; + } + if (Schemas.vscodeRemote === uri.scheme) { + // rewrite vscode-remote-uris to uris of the window location + // so that they can be intercepted by the service worker + return _location.with({ path: '/vscode-remote', query: JSON.stringify(uri) }); + } + return uri; +} diff --git a/src/vs/base/browser/event.ts b/src/vs/base/browser/event.ts index 96297831e74..52cc2ae8281 100644 --- a/src/vs/base/browser/event.ts +++ b/src/vs/base/browser/event.ts @@ -3,18 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Event, Emitter } from 'vs/base/common/event'; +import { Event as BaseEvent, Emitter } from 'vs/base/common/event'; export type EventHandler = HTMLElement | HTMLDocument | Window; export interface IDomEvent { - (element: EventHandler, type: K, useCapture?: boolean): Event; - (element: EventHandler, type: string, useCapture?: boolean): Event; + (element: EventHandler, type: K, useCapture?: boolean): BaseEvent; + (element: EventHandler, type: string, useCapture?: boolean): BaseEvent; } export const domEvent: IDomEvent = (element: EventHandler, type: string, useCapture?: boolean) => { - const fn = e => emitter.fire(e); - const emitter = new Emitter({ + const fn = (e: Event) => emitter.fire(e); + const emitter = new Emitter({ onFirstListenerAdd: () => { element.addEventListener(type, fn, useCapture); }, @@ -27,12 +27,12 @@ export const domEvent: IDomEvent = (element: EventHandler, type: string, useCapt }; export interface CancellableEvent { - preventDefault(); - stopPropagation(); + preventDefault(): void; + stopPropagation(): void; } -export function stop(event: Event): Event { - return Event.map(event, e => { +export function stop(event: BaseEvent): BaseEvent { + return BaseEvent.map(event, e => { e.preventDefault(); e.stopPropagation(); return e; diff --git a/src/vs/base/browser/globalMouseMoveMonitor.ts b/src/vs/base/browser/globalMouseMoveMonitor.ts index 89210064781..109f6f72260 100644 --- a/src/vs/base/browser/globalMouseMoveMonitor.ts +++ b/src/vs/base/browser/globalMouseMoveMonitor.ts @@ -6,7 +6,7 @@ import * as dom from 'vs/base/browser/dom'; import { IframeUtils } from 'vs/base/browser/iframe'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; export interface IStandardMouseMoveEventData { leftButton: boolean; @@ -36,24 +36,16 @@ export function standardMouseMoveMerger(lastEvent: IStandardMouseMoveEventData, }; } -export class GlobalMouseMoveMonitor extends Disposable { +export class GlobalMouseMoveMonitor implements IDisposable { - private hooks: IDisposable[]; - private mouseMoveEventMerger: IEventMerger | null; - private mouseMoveCallback: IMouseMoveCallback | null; - private onStopCallback: IOnStopCallback | null; - - constructor() { - super(); - this.hooks = []; - this.mouseMoveEventMerger = null; - this.mouseMoveCallback = null; - this.onStopCallback = null; - } + private readonly hooks = new DisposableStore(); + private mouseMoveEventMerger: IEventMerger | null = null; + private mouseMoveCallback: IMouseMoveCallback | null = null; + private onStopCallback: IOnStopCallback | null = null; public dispose(): void { this.stopMonitoring(false); - super.dispose(); + this.hooks.dispose(); } public stopMonitoring(invokeStopCallback: boolean): void { @@ -63,10 +55,10 @@ export class GlobalMouseMoveMonitor extends Disposable { } // Unhook - this.hooks = dispose(this.hooks); + this.hooks.clear(); this.mouseMoveEventMerger = null; this.mouseMoveCallback = null; - let onStopCallback = this.onStopCallback; + const onStopCallback = this.onStopCallback; this.onStopCallback = null; if (invokeStopCallback && onStopCallback) { @@ -74,8 +66,8 @@ export class GlobalMouseMoveMonitor extends Disposable { } } - public isMonitoring() { - return this.hooks.length > 0; + public isMonitoring(): boolean { + return !!this.mouseMoveEventMerger; } public startMonitoring( @@ -93,32 +85,32 @@ export class GlobalMouseMoveMonitor extends Disposable { let windowChain = IframeUtils.getSameOriginWindowChain(); for (const element of windowChain) { - this.hooks.push(dom.addDisposableThrottledListener(element.window.document, 'mousemove', + this.hooks.add(dom.addDisposableThrottledListener(element.window.document, 'mousemove', (data: R) => this.mouseMoveCallback!(data), (lastEvent: R, currentEvent) => this.mouseMoveEventMerger!(lastEvent, currentEvent as MouseEvent) )); - this.hooks.push(dom.addDisposableListener(element.window.document, 'mouseup', (e: MouseEvent) => this.stopMonitoring(true))); + this.hooks.add(dom.addDisposableListener(element.window.document, 'mouseup', (e: MouseEvent) => this.stopMonitoring(true))); } if (IframeUtils.hasDifferentOriginAncestor()) { let lastSameOriginAncestor = windowChain[windowChain.length - 1]; // We might miss a mouse up if it happens outside the iframe // This one is for Chrome - this.hooks.push(dom.addDisposableListener(lastSameOriginAncestor.window.document, 'mouseout', (browserEvent: MouseEvent) => { + this.hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document, 'mouseout', (browserEvent: MouseEvent) => { let e = new StandardMouseEvent(browserEvent); if (e.target.tagName.toLowerCase() === 'html') { this.stopMonitoring(true); } })); // This one is for FF - this.hooks.push(dom.addDisposableListener(lastSameOriginAncestor.window.document, 'mouseover', (browserEvent: MouseEvent) => { + this.hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document, 'mouseover', (browserEvent: MouseEvent) => { let e = new StandardMouseEvent(browserEvent); if (e.target.tagName.toLowerCase() === 'html') { this.stopMonitoring(true); } })); // This one is for IE - this.hooks.push(dom.addDisposableListener(lastSameOriginAncestor.window.document.body, 'mouseleave', (browserEvent: MouseEvent) => { + this.hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document.body, 'mouseleave', (browserEvent: MouseEvent) => { this.stopMonitoring(true); })); } diff --git a/src/vs/base/browser/history.ts b/src/vs/base/browser/history.ts index 8c58bf64b00..9da95f45628 100644 --- a/src/vs/base/browser/history.ts +++ b/src/vs/base/browser/history.ts @@ -5,8 +5,8 @@ export interface IHistoryNavigationWidget { - showPreviousValue(); + showPreviousValue(): void; - showNextValue(); + showNextValue(): void; } \ No newline at end of file diff --git a/src/vs/base/browser/htmlContentRenderer.ts b/src/vs/base/browser/htmlContentRenderer.ts index cee63325b9b..4506912e178 100644 --- a/src/vs/base/browser/htmlContentRenderer.ts +++ b/src/vs/base/browser/htmlContentRenderer.ts @@ -6,10 +6,10 @@ import * as DOM from 'vs/base/browser/dom'; import { defaultGenerator } from 'vs/base/common/idGenerator'; import { escape } from 'vs/base/common/strings'; -import { removeMarkdownEscapes, IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent'; +import { removeMarkdownEscapes, IMarkdownString, parseHrefAndDimensions } from 'vs/base/common/htmlContent'; import * as marked from 'vs/base/common/marked/marked'; import { IMouseEvent } from 'vs/base/browser/mouseEvent'; -import { IDisposable } from 'vs/base/common/lifecycle'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { onUnexpectedError } from 'vs/base/common/errors'; import { URI } from 'vs/base/common/uri'; import { parse } from 'vs/base/common/marshalling'; @@ -17,7 +17,7 @@ import { cloneAndChange } from 'vs/base/common/objects'; export interface IContentActionHandler { callback: (content: string, event?: IMouseEvent) => void; - disposeables: IDisposable[]; + readonly disposeables: DisposableStore; } export interface RenderOptions { @@ -75,12 +75,15 @@ export function renderMarkdown(markdown: IMarkdownString, options: RenderOptions return encodeURIComponent(JSON.stringify(data)); }; - const _href = function (href: string): string { + const _href = function (href: string, isDomUri: boolean): string { const data = markdown.uris && markdown.uris[href]; if (!data) { return href; } let uri = URI.revive(data); + if (isDomUri) { + uri = DOM.asDomUri(uri); + } if (uri.query) { uri = uri.with({ query: _uriMassage(uri.query) }); } @@ -97,29 +100,11 @@ export function renderMarkdown(markdown: IMarkdownString, options: RenderOptions const renderer = new marked.Renderer(); renderer.image = (href: string, title: string, text: string) => { - href = _href(href); let dimensions: string[] = []; - if (href) { - const splitted = href.split('|').map(s => s.trim()); - href = splitted[0]; - const parameters = splitted[1]; - if (parameters) { - const heightFromParams = /height=(\d+)/.exec(parameters); - const widthFromParams = /width=(\d+)/.exec(parameters); - const height = heightFromParams ? heightFromParams[1] : ''; - const width = widthFromParams ? widthFromParams[1] : ''; - const widthIsFinite = isFinite(parseInt(width)); - const heightIsFinite = isFinite(parseInt(height)); - if (widthIsFinite) { - dimensions.push(`width="${width}"`); - } - if (heightIsFinite) { - dimensions.push(`height="${height}"`); - } - } - } let attributes: string[] = []; if (href) { + ({ href, dimensions } = parseHrefAndDimensions(href)); + href = _href(href, true); attributes.push(`src="${href}"`); } if (text) { @@ -138,7 +123,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: RenderOptions if (href === text) { // raw link case text = removeMarkdownEscapes(text); } - href = _href(href); + href = _href(href, false); title = removeMarkdownEscapes(title); href = removeMarkdownEscapes(href); if ( @@ -189,7 +174,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: RenderOptions } if (options.actionHandler) { - options.actionHandler.disposeables.push(DOM.addStandardDisposableListener(element, 'click', event => { + options.actionHandler.disposeables.add(DOM.addStandardDisposableListener(element, 'click', event => { let target: HTMLElement | null = event.target; if (target.tagName !== 'A') { target = target.parentElement; @@ -211,7 +196,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: RenderOptions } const markedOptions: marked.MarkedOptions = { - sanitize: markdown instanceof MarkdownString ? markdown.sanitize : true, + sanitize: true, renderer }; @@ -284,7 +269,7 @@ function _renderFormattedText(element: Node, treeNode: IFormatParseTree, actionH else if (treeNode.type === FormatType.Action && actionHandler) { const a = document.createElement('a'); a.href = '#'; - actionHandler.disposeables.push(DOM.addStandardDisposableListener(a, 'click', (event) => { + actionHandler.disposeables.add(DOM.addStandardDisposableListener(a, 'click', (event) => { actionHandler.callback(String(treeNode.index), event); })); @@ -315,7 +300,7 @@ function parseFormattedText(content: string): IFormatParseTree { children: [] }; - let actionItemIndex = 0; + let actionViewItemIndex = 0; let current = root; const stack: IFormatParseTree[] = []; const stream = new StringStream(content); @@ -345,8 +330,8 @@ function parseFormattedText(content: string): IFormatParseTree { }; if (type === FormatType.Action) { - newCurrent.index = actionItemIndex; - actionItemIndex++; + newCurrent.index = actionViewItemIndex; + actionViewItemIndex++; } current.children!.push(newCurrent); diff --git a/src/vs/base/browser/keyboardEvent.ts b/src/vs/base/browser/keyboardEvent.ts index a6fdce5c7c9..03bdffc95ed 100644 --- a/src/vs/base/browser/keyboardEvent.ts +++ b/src/vs/base/browser/keyboardEvent.ts @@ -179,6 +179,9 @@ export function getCodeForKeyCode(keyCode: KeyCode): number { } export interface IKeyboardEvent { + + readonly _standardKeyboardEventBrand: true; + readonly browserEvent: KeyboardEvent; readonly target: HTMLElement; @@ -206,6 +209,8 @@ const metaKeyMod = (platform.isMacintosh ? KeyMod.CtrlCmd : KeyMod.WinCtrl); export class StandardKeyboardEvent implements IKeyboardEvent { + readonly _standardKeyboardEventBrand = true; + public readonly browserEvent: KeyboardEvent; public readonly target: HTMLElement; diff --git a/src/vs/base/browser/mouseEvent.ts b/src/vs/base/browser/mouseEvent.ts index 89ff65ec499..4c7295e3b9b 100644 --- a/src/vs/base/browser/mouseEvent.ts +++ b/src/vs/base/browser/mouseEvent.ts @@ -115,6 +115,13 @@ export class DragMouseEvent extends StandardMouseEvent { export interface IMouseWheelEvent extends MouseEvent { readonly wheelDelta: number; + readonly wheelDeltaX: number; + readonly wheelDeltaY: number; + + readonly deltaX: number; + readonly deltaY: number; + readonly deltaZ: number; + readonly deltaMode: number; } interface IWebKitMouseWheelEvent { @@ -153,6 +160,8 @@ export class StandardWheelEvent { this.deltaY = e1.wheelDeltaY / 120; } else if (typeof e2.VERTICAL_AXIS !== 'undefined' && e2.axis === e2.VERTICAL_AXIS) { this.deltaY = -e2.detail / 3; + } else { + this.deltaY = -e.deltaY / 40; } // horizontal delta scroll @@ -164,6 +173,8 @@ export class StandardWheelEvent { } } else if (typeof e2.HORIZONTAL_AXIS !== 'undefined' && e2.axis === e2.HORIZONTAL_AXIS) { this.deltaX = -e.detail / 3; + } else { + this.deltaX = -e.deltaX / 40; } // Assume a vertical scroll if nothing else worked @@ -188,4 +199,4 @@ export class StandardWheelEvent { } } } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/touch.ts b/src/vs/base/browser/touch.ts index 77f94de61f8..f1ea0ee56ca 100644 --- a/src/vs/base/browser/touch.ts +++ b/src/vs/base/browser/touch.ts @@ -69,7 +69,7 @@ export class Gesture extends Disposable { private static INSTANCE: Gesture; private static HOLD_DELAY = 700; - private dispatched: boolean; + private dispatched = false; private targets: HTMLElement[]; private handle: IDisposable | null; @@ -214,10 +214,10 @@ export class Gesture extends Disposable { } } - private newGestureEvent(type: string, intialTarget?: EventTarget): GestureEvent { + private newGestureEvent(type: string, initialTarget?: EventTarget): GestureEvent { let event = (document.createEvent('CustomEvent')); event.initEvent(type, false, true); - event.initialTarget = intialTarget; + event.initialTarget = initialTarget; return event; } diff --git a/src/vs/base/browser/ui/actionbar/actionbar.ts b/src/vs/base/browser/ui/actionbar/actionbar.ts index 8c071f5934d..538f7fa0dbe 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.ts +++ b/src/vs/base/browser/ui/actionbar/actionbar.ts @@ -6,7 +6,7 @@ import 'vs/css!./actionbar'; import * as platform from 'vs/base/common/platform'; import * as nls from 'vs/nls'; -import { Disposable, dispose } from 'vs/base/common/lifecycle'; +import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle'; import { SelectBox, ISelectOptionItem, ISelectBoxOptions } from 'vs/base/browser/ui/selectBox/selectBox'; import { IAction, IActionRunner, Action, IActionChangeEvent, ActionRunner, IRunEvent } from 'vs/base/common/actions'; import * as DOM from 'vs/base/browser/dom'; @@ -17,30 +17,29 @@ import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview'; import { Event, Emitter } from 'vs/base/common/event'; -export interface IActionItem { +export interface IActionViewItem extends IDisposable { actionRunner: IActionRunner; setActionContext(context: any): void; render(element: HTMLElement): void; isEnabled(): boolean; focus(fromRight?: boolean): void; blur(): void; - dispose(): void; } -export interface IBaseActionItemOptions { +export interface IBaseActionViewItemOptions { draggable?: boolean; isMenu?: boolean; } -export class BaseActionItem extends Disposable implements IActionItem { +export class BaseActionViewItem extends Disposable implements IActionViewItem { element?: HTMLElement; _context: any; _action: IAction; - private _actionRunner: IActionRunner; + private _actionRunner!: IActionRunner; - constructor(context: any, action: IAction, protected options?: IBaseActionItemOptions) { + constructor(context: any, action: IAction, protected options?: IBaseActionViewItemOptions) { super(); this._context = context || this; @@ -225,20 +224,20 @@ export class Separator extends Action { } } -export interface IActionItemOptions extends IBaseActionItemOptions { +export interface IActionViewItemOptions extends IBaseActionViewItemOptions { icon?: boolean; label?: boolean; keybinding?: string | null; } -export class ActionItem extends BaseActionItem { +export class ActionViewItem extends BaseActionViewItem { - protected label: HTMLElement; - protected options: IActionItemOptions; + protected label!: HTMLElement; + protected options: IActionViewItemOptions; private cssClass?: string; - constructor(context: any, action: IAction, options: IActionItemOptions = {}) { + constructor(context: any, action: IAction, options: IActionViewItemOptions = {}) { super(context, action, options); this.options = options; @@ -362,14 +361,14 @@ export interface ActionTrigger { keyDown: boolean; } -export interface IActionItemProvider { - (action: IAction): IActionItem | null; +export interface IActionViewItemProvider { + (action: IAction): IActionViewItem | undefined; } export interface IActionBarOptions { orientation?: ActionsOrientation; context?: any; - actionItemProvider?: IActionItemProvider; + actionViewItemProvider?: IActionViewItemProvider; actionRunner?: IActionRunner; ariaLabel?: string; animated?: boolean; @@ -385,7 +384,7 @@ const defaultOptions: IActionBarOptions = { } }; -export interface IActionOptions extends IActionItemOptions { +export interface IActionOptions extends IActionViewItemOptions { index?: number; } @@ -396,8 +395,8 @@ export class ActionBar extends Disposable implements IActionRunner { private _actionRunner: IActionRunner; private _context: any; - // Items - items: IActionItem[]; + // View Items + viewItems: IActionViewItem[]; protected focusedItem?: number; private focusTracker: DOM.IFocusTracker; @@ -406,16 +405,16 @@ export class ActionBar extends Disposable implements IActionRunner { protected actionsList: HTMLElement; private _onDidBlur = this._register(new Emitter()); - get onDidBlur(): Event { return this._onDidBlur.event; } + readonly onDidBlur: Event = this._onDidBlur.event; private _onDidCancel = this._register(new Emitter()); - get onDidCancel(): Event { return this._onDidCancel.event; } + readonly onDidCancel: Event = this._onDidCancel.event; private _onDidRun = this._register(new Emitter()); - get onDidRun(): Event { return this._onDidRun.event; } + readonly onDidRun: Event = this._onDidRun.event; private _onDidBeforeRun = this._register(new Emitter()); - get onDidBeforeRun(): Event { return this._onDidBeforeRun.event; } + readonly onDidBeforeRun: Event = this._onDidBeforeRun.event; constructor(container: HTMLElement, options: IActionBarOptions = defaultOptions) { super(); @@ -437,7 +436,7 @@ export class ActionBar extends Disposable implements IActionRunner { this._register(this._actionRunner.onDidRun(e => this._onDidRun.fire(e))); this._register(this._actionRunner.onDidBeforeRun(e => this._onDidBeforeRun.fire(e))); - this.items = []; + this.viewItems = []; this.focusedItem = undefined; this.domNode = document.createElement('div'); @@ -574,7 +573,7 @@ export class ActionBar extends Disposable implements IActionRunner { set context(context: any) { this._context = context; - this.items.forEach(i => i.setActionContext(context)); + this.viewItems.forEach(i => i.setActionContext(context)); } get actionRunner(): IActionRunner { @@ -584,7 +583,7 @@ export class ActionBar extends Disposable implements IActionRunner { set actionRunner(actionRunner: IActionRunner) { if (actionRunner) { this._actionRunner = actionRunner; - this.items.forEach(item => item.actionRunner = actionRunner); + this.viewItems.forEach(item => item.actionRunner = actionRunner); } } @@ -592,42 +591,42 @@ export class ActionBar extends Disposable implements IActionRunner { return this.domNode; } - push(arg: IAction | IAction[], options: IActionOptions = {}): void { - const actions: IAction[] = !Array.isArray(arg) ? [arg] : arg; + push(arg: IAction | ReadonlyArray, options: IActionOptions = {}): void { + const actions: ReadonlyArray = Array.isArray(arg) ? arg : [arg]; let index = types.isNumber(options.index) ? options.index : null; actions.forEach((action: IAction) => { - const actionItemElement = document.createElement('li'); - actionItemElement.className = 'action-item'; - actionItemElement.setAttribute('role', 'presentation'); + const actionViewItemElement = document.createElement('li'); + actionViewItemElement.className = 'action-item'; + actionViewItemElement.setAttribute('role', 'presentation'); // Prevent native context menu on actions - this._register(DOM.addDisposableListener(actionItemElement, DOM.EventType.CONTEXT_MENU, (e: DOM.EventLike) => { + this._register(DOM.addDisposableListener(actionViewItemElement, DOM.EventType.CONTEXT_MENU, (e: DOM.EventLike) => { e.preventDefault(); e.stopPropagation(); })); - let item: IActionItem | null = null; + let item: IActionViewItem | undefined; - if (this.options.actionItemProvider) { - item = this.options.actionItemProvider(action); + if (this.options.actionViewItemProvider) { + item = this.options.actionViewItemProvider(action); } if (!item) { - item = new ActionItem(this.context, action, options); + item = new ActionViewItem(this.context, action, options); } item.actionRunner = this._actionRunner; item.setActionContext(this.context); - item.render(actionItemElement); + item.render(actionViewItemElement); if (index === null || index < 0 || index >= this.actionsList.children.length) { - this.actionsList.appendChild(actionItemElement); - this.items.push(item); + this.actionsList.appendChild(actionViewItemElement); + this.viewItems.push(item); } else { - this.actionsList.insertBefore(actionItemElement, this.actionsList.children[index]); - this.items.splice(index, 0, item); + this.actionsList.insertBefore(actionViewItemElement, this.actionsList.children[index]); + this.viewItems.splice(index, 0, item); index++; } }); @@ -656,28 +655,28 @@ export class ActionBar extends Disposable implements IActionRunner { } pull(index: number): void { - if (index >= 0 && index < this.items.length) { + if (index >= 0 && index < this.viewItems.length) { this.actionsList.removeChild(this.actionsList.childNodes[index]); - dispose(this.items.splice(index, 1)); + dispose(this.viewItems.splice(index, 1)); } } clear(): void { - this.items = dispose(this.items); + this.viewItems = dispose(this.viewItems); DOM.clearNode(this.actionsList); } length(): number { - return this.items.length; + return this.viewItems.length; } isEmpty(): boolean { - return this.items.length === 0; + return this.viewItems.length === 0; } focus(index?: number): void; focus(selectFirst?: boolean): void; - focus(arg?: any): void { + focus(arg?: number | boolean): void { let selectFirst: boolean = false; let index: number | undefined = undefined; if (arg === undefined) { @@ -690,7 +689,7 @@ export class ActionBar extends Disposable implements IActionRunner { if (selectFirst && typeof this.focusedItem === 'undefined') { // Focus the first enabled item - this.focusedItem = this.items.length - 1; + this.focusedItem = this.viewItems.length - 1; this.focusNext(); } else { if (index !== undefined) { @@ -703,15 +702,15 @@ export class ActionBar extends Disposable implements IActionRunner { protected focusNext(): void { if (typeof this.focusedItem === 'undefined') { - this.focusedItem = this.items.length - 1; + this.focusedItem = this.viewItems.length - 1; } const startIndex = this.focusedItem; - let item: IActionItem; + let item: IActionViewItem; do { - this.focusedItem = (this.focusedItem + 1) % this.items.length; - item = this.items[this.focusedItem]; + 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()) { @@ -727,16 +726,16 @@ export class ActionBar extends Disposable implements IActionRunner { } const startIndex = this.focusedItem; - let item: IActionItem; + let item: IActionViewItem; do { this.focusedItem = this.focusedItem - 1; if (this.focusedItem < 0) { - this.focusedItem = this.items.length - 1; + this.focusedItem = this.viewItems.length - 1; } - item = this.items[this.focusedItem]; + item = this.viewItems[this.focusedItem]; } while (this.focusedItem !== startIndex && !item.isEnabled()); if (this.focusedItem === startIndex && !item.isEnabled()) { @@ -751,21 +750,21 @@ export class ActionBar extends Disposable implements IActionRunner { this.actionsList.focus(); } - for (let i = 0; i < this.items.length; i++) { - const item = this.items[i]; - const actionItem = item; + for (let i = 0; i < this.viewItems.length; i++) { + const item = this.viewItems[i]; + const actionViewItem = item; if (i === this.focusedItem) { - if (types.isFunction(actionItem.isEnabled)) { - if (actionItem.isEnabled() && types.isFunction(actionItem.focus)) { - actionItem.focus(fromRight); + if (types.isFunction(actionViewItem.isEnabled)) { + if (actionViewItem.isEnabled() && types.isFunction(actionViewItem.focus)) { + actionViewItem.focus(fromRight); } else { this.actionsList.focus(); } } } else { - if (types.isFunction(actionItem.blur)) { - actionItem.blur(); + if (types.isFunction(actionViewItem.blur)) { + actionViewItem.blur(); } } } @@ -777,16 +776,16 @@ export class ActionBar extends Disposable implements IActionRunner { } // trigger action - const actionItem = this.items[this.focusedItem]; - if (actionItem instanceof BaseActionItem) { - const context = (actionItem._context === null || actionItem._context === undefined) ? event : actionItem._context; - this.run(actionItem._action, context); + const actionViewItem = this.viewItems[this.focusedItem]; + if (actionViewItem instanceof BaseActionViewItem) { + const context = (actionViewItem._context === null || actionViewItem._context === undefined) ? event : actionViewItem._context; + this.run(actionViewItem._action, context); } } private cancel(): void { if (document.activeElement instanceof HTMLElement) { - (document.activeElement).blur(); // remove focus from focused action + document.activeElement.blur(); // remove focus from focused action } this._onDidCancel.fire(); @@ -797,8 +796,8 @@ export class ActionBar extends Disposable implements IActionRunner { } dispose(): void { - dispose(this.items); - this.items = []; + dispose(this.viewItems); + this.viewItems = []; DOM.removeNode(this.getContainer()); @@ -806,7 +805,7 @@ export class ActionBar extends Disposable implements IActionRunner { } } -export class SelectActionItem extends BaseActionItem { +export class SelectActionViewItem extends BaseActionViewItem { protected selectBox: SelectBox; constructor(ctx: any, action: IAction, options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, selectBoxOptions?: ISelectBoxOptions) { diff --git a/src/vs/base/browser/ui/aria/aria.ts b/src/vs/base/browser/ui/aria/aria.ts index 1922450144d..fc71827eafa 100644 --- a/src/vs/base/browser/ui/aria/aria.ts +++ b/src/vs/base/browser/ui/aria/aria.ts @@ -33,48 +33,50 @@ export function setARIAContainer(parent: HTMLElement) { /** * Given the provided message, will make sure that it is read as alert to screen readers. */ -export function alert(msg: string): void { - insertMessage(alertContainer, msg); +export function alert(msg: string, disableRepeat?: boolean): void { + insertMessage(alertContainer, msg, disableRepeat); } /** * Given the provided message, will make sure that it is read as status to screen readers. */ -export function status(msg: string): void { +export function status(msg: string, disableRepeat?: boolean): void { if (isMacintosh) { - alert(msg); // VoiceOver does not seem to support status role + alert(msg, disableRepeat); // VoiceOver does not seem to support status role } else { - insertMessage(statusContainer, msg); + insertMessage(statusContainer, msg, disableRepeat); } } let repeatedTimes = 0; let prevText: string | undefined = undefined; -function insertMessage(target: HTMLElement, msg: string): void { +function insertMessage(target: HTMLElement, msg: string, disableRepeat?: boolean): void { if (!ariaContainer) { - // console.warn('ARIA support needs a container. Call setARIAContainer() first.'); return; } - if (prevText === msg) { - repeatedTimes++; - } - else { - prevText = msg; - repeatedTimes = 0; - } + // If the same message should be inserted that is already present, a screen reader would + // not announce this message because it matches the previous one. As a workaround, we + // alter the message with the number of occurences unless this is explicitly disabled + // via the disableRepeat flag. + if (!disableRepeat) { + if (prevText === msg) { + repeatedTimes++; + } else { + prevText = msg; + repeatedTimes = 0; + } - - switch (repeatedTimes) { - case 0: break; - case 1: msg = nls.localize('repeated', "{0} (occurred again)", msg); break; - default: msg = nls.localize('repeatedNtimes', "{0} (occurred {1} times)", msg, repeatedTimes); break; + switch (repeatedTimes) { + case 0: break; + case 1: msg = nls.localize('repeated', "{0} (occurred again)", msg); break; + default: msg = nls.localize('repeatedNtimes', "{0} (occurred {1} times)", msg, repeatedTimes); break; + } } dom.clearNode(target); target.textContent = msg; - // See https://www.paciellogroup.com/blog/2012/06/html5-accessibility-chops-aria-rolealert-browser-support/ target.style.visibility = 'hidden'; target.style.visibility = 'visible'; diff --git a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.css b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.css index afade1a3413..1e49da134fd 100644 --- a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.css +++ b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.css @@ -31,12 +31,16 @@ } .monaco-breadcrumbs .monaco-breadcrumb-item:not(:nth-child(2))::before { - background-image: url(./collapsed.svg); + background-image: url(./tree-collapsed-light.svg); opacity: .7; background-size: 16px; background-position: 50% 50%; } .vs-dark .monaco-breadcrumbs .monaco-breadcrumb-item:not(:nth-child(2))::before { - background-image: url(./collpased-dark.svg); + background-image: url(./tree-collapsed-dark.svg); +} + +.hc-black .monaco-breadcrumbs .monaco-breadcrumb-item:not(:nth-child(2))::before { + background-image: url(./tree-collapsed-hc.svg); } diff --git a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts index 42f43d27322..2e72938f986 100644 --- a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts +++ b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts @@ -9,7 +9,7 @@ import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableEle import { commonPrefixLength } from 'vs/base/common/arrays'; import { Color } from 'vs/base/common/color'; import { Emitter, Event } from 'vs/base/common/event'; -import { dispose, IDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; +import { dispose, IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import 'vs/css!./breadcrumbsWidget'; @@ -57,7 +57,7 @@ export interface IBreadcrumbsItemEvent { export class BreadcrumbsWidget { - private readonly _disposables = new Array(); + private readonly _disposables = new DisposableStore(); private readonly _domNode: HTMLDivElement; private readonly _styleElement: HTMLStyleElement; private readonly _scrollable: DomScrollableElement; @@ -77,8 +77,8 @@ export class BreadcrumbsWidget { private _focusedItemIdx: number = -1; private _selectedItemIdx: number = -1; - private _pendingLayout: IDisposable; - private _dimension: dom.Dimension; + private _pendingLayout: IDisposable | undefined; + private _dimension: dom.Dimension | undefined; constructor( container: HTMLElement @@ -94,26 +94,25 @@ export class BreadcrumbsWidget { useShadows: false, scrollYToX: true }); - this._disposables.push(this._scrollable); - this._disposables.push(dom.addStandardDisposableListener(this._domNode, 'click', e => this._onClick(e))); + this._disposables.add(this._scrollable); + this._disposables.add(dom.addStandardDisposableListener(this._domNode, 'click', e => this._onClick(e))); container.appendChild(this._scrollable.getDomNode()); this._styleElement = dom.createStyleSheet(this._domNode); - let focusTracker = dom.trackFocus(this._domNode); - this._disposables.push(focusTracker); - this._disposables.push(focusTracker.onDidBlur(_ => this._onDidChangeFocus.fire(false))); - this._disposables.push(focusTracker.onDidFocus(_ => this._onDidChangeFocus.fire(true))); + const focusTracker = dom.trackFocus(this._domNode); + this._disposables.add(focusTracker); + this._disposables.add(focusTracker.onDidBlur(_ => this._onDidChangeFocus.fire(false))); + this._disposables.add(focusTracker.onDidFocus(_ => this._onDidChangeFocus.fire(true))); } dispose(): void { - dispose(this._disposables); + this._disposables.dispose(); dispose(this._pendingLayout); this._onDidSelectItem.dispose(); this._onDidFocusItem.dispose(); this._onDidChangeFocus.dispose(); this._domNode.remove(); - this._disposables.length = 0; this._nodes.length = 0; this._freeNodes.length = 0; } @@ -126,7 +125,7 @@ export class BreadcrumbsWidget { this._pendingLayout.dispose(); } if (dim) { - // only meaure + // only measure this._pendingLayout = this._updateDimensions(dim); } else { this._pendingLayout = this._updateScrollbar(); @@ -134,14 +133,14 @@ export class BreadcrumbsWidget { } private _updateDimensions(dim: dom.Dimension): IDisposable { - let disposables: IDisposable[] = []; - disposables.push(dom.modify(() => { + const disposables = new DisposableStore(); + disposables.add(dom.modify(() => { this._dimension = dim; this._domNode.style.width = `${dim.width}px`; this._domNode.style.height = `${dim.height}px`; - disposables.push(this._updateScrollbar()); + disposables.add(this._updateScrollbar()); })); - return combinedDisposable(disposables); + return disposables; } private _updateScrollbar(): IDisposable { @@ -200,8 +199,8 @@ export class BreadcrumbsWidget { return this._items[this._focusedItemIdx]; } - setFocused(item: BreadcrumbsItem, payload?: any): void { - this._focus(this._items.indexOf(item), payload); + setFocused(item: BreadcrumbsItem | undefined, payload?: any): void { + this._focus(this._items.indexOf(item!), payload); } focusPrev(payload?: any): any { @@ -256,8 +255,8 @@ export class BreadcrumbsWidget { return this._items[this._selectedItemIdx]; } - setSelection(item: BreadcrumbsItem, payload?: any): void { - this._select(this._items.indexOf(item), payload); + setSelection(item: BreadcrumbsItem | undefined, payload?: any): void { + this._select(this._items.indexOf(item!), payload); } private _select(nth: number, payload: any): void { @@ -274,7 +273,7 @@ export class BreadcrumbsWidget { this._onDidSelectItem.fire({ type: 'select', item: this._items[this._selectedItemIdx], node: this._nodes[this._selectedItemIdx], payload }); } - getItems(): ReadonlyArray { + getItems(): readonly BreadcrumbsItem[] { return this._items; } @@ -334,7 +333,7 @@ export class BreadcrumbsWidget { private _onClick(event: IMouseEvent): void { for (let el: HTMLElement | null = event.target; el; el = el.parentElement) { - let idx = this._nodes.indexOf(el as any); + let idx = this._nodes.indexOf(el as HTMLDivElement); if (idx >= 0) { this._focus(idx, event); this._select(idx, event); diff --git a/src/vs/base/browser/ui/breadcrumbs/collpased-dark.svg b/src/vs/base/browser/ui/breadcrumbs/collpased-dark.svg deleted file mode 100755 index cf5c3641aa7..00000000000 --- a/src/vs/base/browser/ui/breadcrumbs/collpased-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-dark.svg b/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-dark.svg new file mode 100644 index 00000000000..243be1451cc --- /dev/null +++ b/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-hc.svg b/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-hc.svg new file mode 100644 index 00000000000..40ba72b7086 --- /dev/null +++ b/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-light.svg b/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-light.svg new file mode 100644 index 00000000000..0d746558a4f --- /dev/null +++ b/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/button/button.ts b/src/vs/base/browser/ui/button/button.ts index 9b7145f053c..eeb7724e5fd 100644 --- a/src/vs/base/browser/ui/button/button.ts +++ b/src/vs/base/browser/ui/button/button.ts @@ -11,7 +11,7 @@ import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; import { Event as BaseEvent, Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { Gesture } from 'vs/base/browser/touch'; +import { Gesture, EventType } from 'vs/base/browser/touch'; export interface IButtonOptions extends IButtonStyles { title?: boolean; @@ -40,7 +40,7 @@ export class Button extends Disposable { private buttonForeground: Color | undefined; private buttonBorder: Color | undefined; - private _onDidClick = this._register(new Emitter()); + private _onDidClick = this._register(new Emitter()); get onDidClick(): BaseEvent { return this._onDidClick.event; } private focusTracker: DOM.IFocusTracker; @@ -65,14 +65,16 @@ export class Button extends Disposable { Gesture.addTarget(this._element); - this._register(DOM.addDisposableListener(this._element, DOM.EventType.CLICK, e => { - if (!this.enabled) { - DOM.EventHelper.stop(e); - return; - } + [DOM.EventType.CLICK, EventType.Tap].forEach(eventType => { + this._register(DOM.addDisposableListener(this._element, eventType, e => { + if (!this.enabled) { + DOM.EventHelper.stop(e); + return; + } - this._onDidClick.fire(e); - })); + this._onDidClick.fire(e); + })); + }); this._register(DOM.addDisposableListener(this._element, DOM.EventType.KEY_DOWN, e => { const event = new StandardKeyboardEvent(e); @@ -221,4 +223,4 @@ export class ButtonGroup extends Disposable { } } } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/centered/centeredViewLayout.ts b/src/vs/base/browser/ui/centered/centeredViewLayout.ts index 1b1710bed0c..43f665fbd00 100644 --- a/src/vs/base/browser/ui/centered/centeredViewLayout.ts +++ b/src/vs/base/browser/ui/centered/centeredViewLayout.ts @@ -6,8 +6,8 @@ import { SplitView, Orientation, ISplitViewStyles, IView as ISplitViewView } from 'vs/base/browser/ui/splitview/splitview'; import { $ } from 'vs/base/browser/dom'; import { Event } from 'vs/base/common/event'; -import { IView } from 'vs/base/browser/ui/grid/gridview'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IView, IViewSize } from 'vs/base/browser/ui/grid/grid'; +import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { Color } from 'vs/base/common/color'; export interface CenteredViewState { @@ -20,10 +20,12 @@ const GOLDEN_RATIO = { rightMarginRatio: 0.1909 }; -function createEmptyView(background: Color): ISplitViewView { +function createEmptyView(background: Color | undefined): ISplitViewView { const element = $('.centered-layout-margin'); element.style.height = '100%'; - element.style.backgroundColor = background.toString(); + if (background) { + element.style.backgroundColor = background.toString(); + } return { element, @@ -40,7 +42,7 @@ function toSplitViewView(view: IView, getHeight: () => number): ISplitViewView { get maximumSize() { return view.maximumWidth; }, get minimumSize() { return view.minimumWidth; }, onDidChange: Event.map(view.onDidChange, e => e && e.width), - layout: size => view.layout(size, getHeight()) + layout: size => view.layout(size, getHeight(), Orientation.HORIZONTAL) }; } @@ -48,15 +50,15 @@ export interface ICenteredViewStyles extends ISplitViewStyles { background: Color; } -export class CenteredViewLayout { +export class CenteredViewLayout implements IDisposable { private splitView?: SplitView; private width: number = 0; private height: number = 0; - private style: ICenteredViewStyles; + private style!: ICenteredViewStyles; private didLayout = false; private emptyViews: ISplitViewView[] | undefined; - private splitViewDisposables: IDisposable[] = []; + private readonly splitViewDisposables = new DisposableStore(); constructor(private container: HTMLElement, private view: IView, public readonly state: CenteredViewState = { leftMarginRatio: GOLDEN_RATIO.leftMarginRatio, rightMarginRatio: GOLDEN_RATIO.rightMarginRatio }) { this.container.appendChild(this.view.element); @@ -68,6 +70,7 @@ export class CenteredViewLayout { get maximumWidth(): number { return this.splitView ? this.splitView.maximumSize : this.view.maximumWidth; } get minimumHeight(): number { return this.view.minimumHeight; } get maximumHeight(): number { return this.view.maximumHeight; } + get onDidChange(): Event { return this.view.onDidChange; } layout(width: number, height: number): void { this.width = width; @@ -78,7 +81,7 @@ export class CenteredViewLayout { this.resizeMargins(); } } else { - this.view.layout(width, height); + this.view.layout(width, height, Orientation.HORIZONTAL); } this.didLayout = true; } @@ -117,13 +120,13 @@ export class CenteredViewLayout { styles: this.style }); - this.splitViewDisposables.push(this.splitView.onDidSashChange(() => { + this.splitViewDisposables.add(this.splitView.onDidSashChange(() => { if (this.splitView) { this.state.leftMarginRatio = this.splitView.getViewSize(0) / this.width; this.state.rightMarginRatio = this.splitView.getViewSize(2) / this.width; } })); - this.splitViewDisposables.push(this.splitView.onDidSashReset(() => { + this.splitViewDisposables.add(this.splitView.onDidSashReset(() => { this.state.leftMarginRatio = GOLDEN_RATIO.leftMarginRatio; this.state.rightMarginRatio = GOLDEN_RATIO.rightMarginRatio; this.resizeMargins(); @@ -131,14 +134,15 @@ export class CenteredViewLayout { this.splitView.layout(this.width); this.splitView.addView(toSplitViewView(this.view, () => this.height), 0); - this.emptyViews = [createEmptyView(this.style.background), createEmptyView(this.style.background)]; + const backgroundColor = this.style ? this.style.background : undefined; + this.emptyViews = [createEmptyView(backgroundColor), createEmptyView(backgroundColor)]; this.splitView.addView(this.emptyViews[0], this.state.leftMarginRatio * this.width, 0); this.splitView.addView(this.emptyViews[1], this.state.rightMarginRatio * this.width, 2); } else { if (this.splitView) { this.container.removeChild(this.splitView.el); } - this.splitViewDisposables = dispose(this.splitViewDisposables); + this.splitViewDisposables.clear(); if (this.splitView) { this.splitView.dispose(); } @@ -153,7 +157,7 @@ export class CenteredViewLayout { } dispose(): void { - this.splitViewDisposables = dispose(this.splitViewDisposables); + this.splitViewDisposables.dispose(); if (this.splitView) { this.splitView.dispose(); diff --git a/src/vs/base/browser/ui/checkbox/checkbox.ts b/src/vs/base/browser/ui/checkbox/checkbox.ts index 73f7ca9722e..ed0bcfa0ab1 100644 --- a/src/vs/base/browser/ui/checkbox/checkbox.ts +++ b/src/vs/base/browser/ui/checkbox/checkbox.ts @@ -11,8 +11,8 @@ import { Color } from 'vs/base/common/color'; import { Emitter, Event } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; import * as objects from 'vs/base/common/objects'; -import { BaseActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; +import { DisposableStore } from 'vs/base/common/lifecycle'; export interface ICheckboxOpts extends ICheckboxStyles { readonly actionClassName?: string; @@ -22,28 +22,30 @@ export interface ICheckboxOpts extends ICheckboxStyles { export interface ICheckboxStyles { inputActiveOptionBorder?: Color; + inputActiveOptionBackground?: Color; } const defaultOpts = { - inputActiveOptionBorder: Color.fromHex('#007ACC') + inputActiveOptionBorder: Color.fromHex('#007ACC00'), + inputActiveOptionBackground: Color.fromHex('#0E639C50') }; -export class CheckboxActionItem extends BaseActionItem { +export class CheckboxActionViewItem extends BaseActionViewItem { - private checkbox: Checkbox; - private disposables: IDisposable[] = []; + private checkbox!: Checkbox; + private readonly disposables = new DisposableStore(); render(container: HTMLElement): void { this.element = container; - this.disposables = dispose(this.disposables); + this.disposables.clear(); this.checkbox = new Checkbox({ actionClassName: this._action.class, isChecked: this._action.checked, title: this._action.label }); - this.disposables.push(this.checkbox); - this.checkbox.onChange(() => this._action.checked = this.checkbox.checked, this, this.disposables); + this.disposables.add(this.checkbox); + this.disposables.add(this.checkbox.onChange(() => this._action.checked = this.checkbox!.checked, this)); this.element.appendChild(this.checkbox.domNode); } @@ -63,20 +65,19 @@ export class CheckboxActionItem extends BaseActionItem { } } - dipsose(): void { - this.disposables = dispose(this.disposables); + dispose(): void { + this.disposables.dispose(); super.dispose(); } - } export class Checkbox extends Widget { private readonly _onChange = this._register(new Emitter()); - get onChange(): Event { return this._onChange.event; } + readonly onChange: Event = this._onChange.event; private readonly _onKeyDown = this._register(new Emitter()); - get onKeyDown(): Event { return this._onKeyDown.event; } + readonly onKeyDown: Event = this._onKeyDown.event; private readonly _opts: ICheckboxOpts; readonly domNode: HTMLElement; @@ -150,12 +151,16 @@ export class Checkbox extends Widget { if (styles.inputActiveOptionBorder) { this._opts.inputActiveOptionBorder = styles.inputActiveOptionBorder; } + if (styles.inputActiveOptionBackground) { + this._opts.inputActiveOptionBackground = styles.inputActiveOptionBackground; + } this.applyStyles(); } protected applyStyles(): void { if (this.domNode) { this.domNode.style.borderColor = this._checked && this._opts.inputActiveOptionBorder ? this._opts.inputActiveOptionBorder.toString() : 'transparent'; + this.domNode.style.backgroundColor = this._checked && this._opts.inputActiveOptionBackground ? this._opts.inputActiveOptionBackground.toString() : 'transparent'; } } diff --git a/src/vs/base/browser/ui/contextview/contextview.ts b/src/vs/base/browser/ui/contextview/contextview.ts index 97545edba8e..8b8bb3b16eb 100644 --- a/src/vs/base/browser/ui/contextview/contextview.ts +++ b/src/vs/base/browser/ui/contextview/contextview.ts @@ -5,7 +5,7 @@ import 'vs/css!./contextview'; import * as DOM from 'vs/base/browser/dom'; -import { IDisposable, dispose, toDisposable, combinedDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { Range } from 'vs/base/common/range'; export interface IAnchor { @@ -100,11 +100,11 @@ export class ContextView extends Disposable { private static readonly BUBBLE_UP_EVENTS = ['click', 'keydown', 'focus', 'blur']; private static readonly BUBBLE_DOWN_EVENTS = ['click']; - private container: HTMLElement | null; + private container: HTMLElement | null = null; private view: HTMLElement; - private delegate: IDelegate | null; - private toDisposeOnClean: IDisposable | null; - private toDisposeOnSetContainer: IDisposable; + private delegate: IDelegate | null = null; + private toDisposeOnClean: IDisposable = Disposable.None; + private toDisposeOnSetContainer: IDisposable = Disposable.None; constructor(container: HTMLElement) { super(); @@ -118,9 +118,9 @@ export class ContextView extends Disposable { this._register(toDisposable(() => this.setContainer(null))); } - public setContainer(container: HTMLElement | null): void { + setContainer(container: HTMLElement | null): void { if (this.container) { - this.toDisposeOnSetContainer = dispose(this.toDisposeOnSetContainer); + this.toDisposeOnSetContainer.dispose(); this.container.removeChild(this.view); this.container = null; } @@ -128,25 +128,25 @@ export class ContextView extends Disposable { this.container = container; this.container.appendChild(this.view); - const toDisposeOnSetContainer: IDisposable[] = []; + const toDisposeOnSetContainer = new DisposableStore(); ContextView.BUBBLE_UP_EVENTS.forEach(event => { - toDisposeOnSetContainer.push(DOM.addStandardDisposableListener(this.container!, event, (e: Event) => { - this.onDOMEvent(e, document.activeElement, false); + toDisposeOnSetContainer.add(DOM.addStandardDisposableListener(this.container!, event, (e: Event) => { + this.onDOMEvent(e, false); })); }); ContextView.BUBBLE_DOWN_EVENTS.forEach(event => { - toDisposeOnSetContainer.push(DOM.addStandardDisposableListener(this.container!, event, (e: Event) => { - this.onDOMEvent(e, document.activeElement, true); + toDisposeOnSetContainer.add(DOM.addStandardDisposableListener(this.container!, event, (e: Event) => { + this.onDOMEvent(e, true); }, true)); }); - this.toDisposeOnSetContainer = combinedDisposable(toDisposeOnSetContainer); + this.toDisposeOnSetContainer = toDisposeOnSetContainer; } } - public show(delegate: IDelegate): void { + show(delegate: IDelegate): void { if (this.isVisible()) { this.hide(); } @@ -159,7 +159,7 @@ export class ContextView extends Disposable { DOM.show(this.view); // Render content - this.toDisposeOnClean = delegate.render(this.view); + this.toDisposeOnClean = delegate.render(this.view) || Disposable.None; // Set active delegate this.delegate = delegate; @@ -173,7 +173,7 @@ export class ContextView extends Disposable { } } - public layout(): void { + layout(): void { if (!this.isVisible()) { return; } @@ -213,13 +213,11 @@ export class ContextView extends Disposable { height: elementPosition.height }; } else { - let realAnchor = anchor; - around = { - top: realAnchor.y, - left: realAnchor.x, - width: realAnchor.width || 1, - height: realAnchor.height || 2 + top: anchor.y, + left: anchor.x, + width: anchor.width || 1, + height: anchor.height || 2 }; } @@ -244,6 +242,9 @@ export class ContextView extends Disposable { // if view intersects vertically with anchor, shift it horizontally if (Range.intersects({ start: top, end: top + viewSizeHeight }, { start: verticalAnchor.offset, end: verticalAnchor.offset + verticalAnchor.size })) { horizontalAnchor.size = around.width; + if (anchorAlignment === AnchorAlignment.RIGHT) { + horizontalAnchor.offset = around.left; + } } const left = layout(window.innerWidth, viewSizeWidth, horizontalAnchor); @@ -258,18 +259,16 @@ export class ContextView extends Disposable { this.view.style.width = 'initial'; } - public hide(data?: any): void { - if (this.delegate && this.delegate.onHide) { - this.delegate.onHide(data); - } - + hide(data?: any): void { + const delegate = this.delegate; this.delegate = null; - if (this.toDisposeOnClean) { - this.toDisposeOnClean.dispose(); - this.toDisposeOnClean = null; + if (delegate && delegate.onHide) { + delegate.onHide(data); } + this.toDisposeOnClean.dispose(); + DOM.hide(this.view); } @@ -277,7 +276,7 @@ export class ContextView extends Disposable { return !!this.delegate; } - private onDOMEvent(e: Event, element: HTMLElement, onCapture: boolean): void { + private onDOMEvent(e: Event, onCapture: boolean): void { if (this.delegate) { if (this.delegate.onDOMEvent) { this.delegate.onDOMEvent(e, document.activeElement); @@ -287,9 +286,9 @@ export class ContextView extends Disposable { } } - public dispose(): void { + dispose(): void { this.hide(); super.dispose(); } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/countBadge/countBadge.css b/src/vs/base/browser/ui/countBadge/countBadge.css index 7429322f3e6..909fa7c8e78 100644 --- a/src/vs/base/browser/ui/countBadge/countBadge.css +++ b/src/vs/base/browser/ui/countBadge/countBadge.css @@ -4,11 +4,12 @@ *--------------------------------------------------------------------------------------------*/ .monaco-count-badge { - padding: 0.3em 0.5em; - border-radius: 1em; - font-size: 85%; - min-width: 1.6em; - line-height: 1em; + padding: 3px 5px; + border-radius: 11px; + font-size: 11px; + min-width: 18px; + min-height: 18px; + line-height: 11px; font-weight: normal; text-align: center; display: inline-block; diff --git a/src/vs/base/browser/ui/countBadge/countBadge.ts b/src/vs/base/browser/ui/countBadge/countBadge.ts index c35b5733ff9..e4b1f68568f 100644 --- a/src/vs/base/browser/ui/countBadge/countBadge.ts +++ b/src/vs/base/browser/ui/countBadge/countBadge.ts @@ -29,7 +29,7 @@ const defaultOpts = { export class CountBadge { private element: HTMLElement; - private count: number; + private count: number = 0; private countFormat: string; private titleFormat: string; diff --git a/src/vs/base/browser/ui/dialog/close-dark.svg b/src/vs/base/browser/ui/dialog/close-dark.svg new file mode 100644 index 00000000000..7305a8f099a --- /dev/null +++ b/src/vs/base/browser/ui/dialog/close-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/dialog/close-light.svg b/src/vs/base/browser/ui/dialog/close-light.svg new file mode 100644 index 00000000000..ecddcd665b5 --- /dev/null +++ b/src/vs/base/browser/ui/dialog/close-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/dialog/dialog.css b/src/vs/base/browser/ui/dialog/dialog.css new file mode 100644 index 00000000000..e05ed90a949 --- /dev/null +++ b/src/vs/base/browser/ui/dialog/dialog.css @@ -0,0 +1,178 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +/** Dialog: Modal Block */ +.monaco-workbench .dialog-modal-block { + position: fixed; + height: 100%; + width: 100%; + left:0; + top:0; + z-index: 2000; + display: flex; + justify-content: center; + align-items: center; +} + +.monaco-workbench .dialog-modal-block.dimmed { + background: rgba(0, 0, 0, 0.3); +} + +/** Dialog: Container */ +.monaco-workbench .dialog-box { + display: flex; + flex-direction: column-reverse; + width: min-content; + min-width: 500px; + max-width: 90%; + min-height: 75px; + padding: 5px; +} + +/** Dialog: Title Actions Row */ +.monaco-workbench .dialog-box .dialog-toolbar-row { + padding-right: 1px; +} + +.monaco-workbench .dialog-box .action-label { + height: 16px; + min-width: 16px; + background-size: 16px; + background-position: 50%; + background-repeat: no-repeat; + margin: 0px; + margin-left: 4px; +} + + +.monaco-workbench .dialog-box .dialog-close-action { + background: url('close-light.svg') center center no-repeat; +} + +.vs-dark .monaco-workbench .dialog-box .dialog-close-action, +.hc-black .monaco-workbench .dialog-box .dialog-close-action { + background: url('close-dark.svg') center center no-repeat; +} + +/** Dialog: Message Row */ +.monaco-workbench .dialog-box .dialog-message-row { + display: flex; + flex-grow: 1; + padding: 10px 15px 20px; + align-items: center; +} + +.monaco-workbench .dialog-box .dialog-message-row .dialog-icon { + flex: 0 0 40px; + height: 40px; + align-self: baseline; + background-position: center; + background-repeat: no-repeat; + background-size: 40px; +} + +.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending { + background-image: url('pending.svg'); +} + +.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info { + background-image: url('info-light.svg'); +} + +.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-warning { + background-image: url('warning-light.svg'); +} + +.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-error { + background-image: url('error-light.svg'); +} + +.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending { + background-image: url('pending-dark.svg'); +} + +.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info, +.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info { + background-image: url('info-dark.svg'); +} + +.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-warning, +.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-warning { + background-image: url('warning-dark.svg'); +} + +.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-error, +.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-error { + background-image: url('error-dark.svg'); +} + +.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending { + background-image: url('pending-hc.svg'); +} + +.monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending { + background-size: 30px; +} + +/** Dialog: Message Container */ +.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container { + display: flex; + flex-direction: column; + overflow: hidden; + text-overflow: ellipsis; + padding-left: 20px; + user-select: text; + word-wrap: break-word; /* never overflow long words, but break to next line */ + white-space: normal; +} + +/** Dialog: Message */ +.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container .dialog-message { + line-height: 22px; + font-size: 18px; + flex: 1; /* let the message always grow */ + white-space: normal; + word-wrap: break-word; /* never overflow long words, but break to next line */ + padding-bottom: 10px; +} + +/** Dialog: Details */ +.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container .dialog-message-detail { + line-height: 22px; + flex: 1; /* let the message always grow */ + opacity: .9; +} + +.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container .dialog-message a:focus { + outline-width: 1px; + outline-style: solid; +} + +/** Dialog: Buttons Row */ +.monaco-workbench .dialog-box > .dialog-buttons-row { + display: flex; + align-items: center; + justify-content: flex-end; + padding-right: 1px; + overflow: hidden; /* buttons row should never overflow */ +} + +.monaco-workbench .dialog-box > .dialog-buttons-row { + display: flex; + white-space: nowrap; +} + +/** Dialog: Buttons */ +.monaco-workbench .dialog-box > .dialog-buttons-row > .dialog-buttons { + display: flex; + overflow: hidden; +} + +.monaco-workbench .dialog-box > .dialog-buttons-row > .dialog-buttons > .monaco-button { + max-width: fit-content; + padding: 5px 10px; + margin: 4px 5px; /* allows button focus outline to be visible */ + overflow: hidden; + text-overflow: ellipsis; +} \ No newline at end of file diff --git a/src/vs/base/browser/ui/dialog/dialog.ts b/src/vs/base/browser/ui/dialog/dialog.ts new file mode 100644 index 00000000000..2b5d836146d --- /dev/null +++ b/src/vs/base/browser/ui/dialog/dialog.ts @@ -0,0 +1,264 @@ +/*--------------------------------------------------------------------------------------------- + * 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!./dialog'; +import * as nls from 'vs/nls'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { $, hide, show, EventHelper, clearNode, removeClasses, addClass, removeNode, isAncestor } from 'vs/base/browser/dom'; +import { domEvent } from 'vs/base/browser/event'; +import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { Color } from 'vs/base/common/color'; +import { ButtonGroup, IButtonStyles } from 'vs/base/browser/ui/button/button'; +import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; +import { Action } from 'vs/base/common/actions'; +import { mnemonicButtonLabel } from 'vs/base/common/labels'; +import { isMacintosh, isLinux } from 'vs/base/common/platform'; + +export interface IDialogOptions { + cancelId?: number; + detail?: string; + type?: 'none' | 'info' | 'error' | 'question' | 'warning' | 'pending'; + keyEventProcessor?: (event: StandardKeyboardEvent) => void; +} + +export interface IDialogStyles extends IButtonStyles { + dialogForeground?: Color; + dialogBackground?: Color; + dialogShadow?: Color; + dialogBorder?: Color; +} + +interface ButtonMapEntry { + label: string; + index: number; +} + +export class Dialog extends Disposable { + private element: HTMLElement | undefined; + private modal: HTMLElement | undefined; + private buttonsContainer: HTMLElement | undefined; + private messageDetailElement: HTMLElement | undefined; + private iconElement: HTMLElement | undefined; + private toolbarContainer: HTMLElement | undefined; + private buttonGroup: ButtonGroup | undefined; + private styles: IDialogStyles | undefined; + private focusToReturn: HTMLElement | undefined; + + constructor(private container: HTMLElement, private message: string, private buttons: string[], private options: IDialogOptions) { + super(); + this.modal = this.container.appendChild($(`.dialog-modal-block${options.type === 'pending' ? '.dimmed' : ''}`)); + this.element = this.modal.appendChild($('.dialog-box')); + hide(this.element); + + const buttonsRowElement = this.element.appendChild($('.dialog-buttons-row')); + this.buttonsContainer = buttonsRowElement.appendChild($('.dialog-buttons')); + + const messageRowElement = this.element.appendChild($('.dialog-message-row')); + this.iconElement = messageRowElement.appendChild($('.dialog-icon')); + const messageContainer = messageRowElement.appendChild($('.dialog-message-container')); + + if (this.options.detail) { + const messageElement = messageContainer.appendChild($('.dialog-message')); + messageElement.innerText = this.message; + } + + this.messageDetailElement = messageContainer.appendChild($('.dialog-message-detail')); + this.messageDetailElement.innerText = this.options.detail ? this.options.detail : message; + + const toolbarRowElement = this.element.appendChild($('.dialog-toolbar-row')); + this.toolbarContainer = toolbarRowElement.appendChild($('.dialog-toolbar')); + } + + updateMessage(message: string): void { + if (this.messageDetailElement) { + this.messageDetailElement.innerText = message; + } + } + + async show(): Promise { + this.focusToReturn = document.activeElement as HTMLElement; + + return new Promise((resolve) => { + if (!this.element || !this.buttonsContainer || !this.iconElement || !this.toolbarContainer) { + resolve(0); + return; + } + + if (this.modal) { + this._register(domEvent(this.modal, 'mousedown')(e => { + // Used to stop focusing of modal with mouse + EventHelper.stop(e, true); + })); + } + + clearNode(this.buttonsContainer); + + let focusedButton = 0; + const buttonGroup = this.buttonGroup = new ButtonGroup(this.buttonsContainer, this.buttons.length, { title: true }); + const buttonMap = this.rearrangeButtons(this.buttons, this.options.cancelId); + + // Set focused button to UI index + buttonMap.forEach((value, index) => { + if (value.index === 0) { + focusedButton = index; + } + }); + + buttonGroup.buttons.forEach((button, index) => { + button.label = mnemonicButtonLabel(buttonMap[index].label, true); + + this._register(button.onDidClick(e => { + EventHelper.stop(e); + resolve(buttonMap[index].index); + })); + }); + + this._register(domEvent(window, 'keydown', true)((e: KeyboardEvent) => { + const evt = new StandardKeyboardEvent(e); + if (evt.equals(KeyCode.Enter) || evt.equals(KeyCode.Space)) { + return; + } + + let eventHandled = false; + if (evt.equals(KeyMod.Shift | KeyCode.Tab) || evt.equals(KeyCode.LeftArrow)) { + focusedButton = focusedButton + buttonGroup.buttons.length - 1; + focusedButton = focusedButton % buttonGroup.buttons.length; + buttonGroup.buttons[focusedButton].focus(); + eventHandled = true; + } else if (evt.equals(KeyCode.Tab) || evt.equals(KeyCode.RightArrow)) { + focusedButton++; + focusedButton = focusedButton % buttonGroup.buttons.length; + buttonGroup.buttons[focusedButton].focus(); + eventHandled = true; + } + + if (eventHandled) { + EventHelper.stop(e, true); + } else if (this.options.keyEventProcessor) { + this.options.keyEventProcessor(evt); + } + })); + + this._register(domEvent(window, 'keyup', true)((e: KeyboardEvent) => { + EventHelper.stop(e, true); + const evt = new StandardKeyboardEvent(e); + + if (evt.equals(KeyCode.Escape)) { + resolve(this.options.cancelId || 0); + } + })); + + this._register(domEvent(this.element, 'focusout', false)((e: FocusEvent) => { + if (!!e.relatedTarget && !!this.element) { + if (!isAncestor(e.relatedTarget as HTMLElement, this.element)) { + this.focusToReturn = e.relatedTarget as HTMLElement; + + if (e.target) { + (e.target as HTMLElement).focus(); + EventHelper.stop(e, true); + } + } + } + })); + + removeClasses(this.iconElement, 'icon-error', 'icon-warning', 'icon-info'); + + switch (this.options.type) { + case 'error': + addClass(this.iconElement, 'icon-error'); + break; + case 'warning': + addClass(this.iconElement, 'icon-warning'); + break; + case 'pending': + addClass(this.iconElement, 'icon-pending'); + break; + case 'none': + case 'info': + case 'question': + default: + addClass(this.iconElement, 'icon-info'); + break; + } + + const actionBar = new ActionBar(this.toolbarContainer, {}); + + const action = new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), 'dialog-close-action', true, () => { + resolve(this.options.cancelId || 0); + return Promise.resolve(); + }); + + actionBar.push(action, { icon: true, label: false, }); + + this.applyStyles(); + + this.element.setAttribute('aria-label', this.message); + show(this.element); + + // Focus first element + buttonGroup.buttons[focusedButton].focus(); + }); + } + + private applyStyles() { + if (this.styles) { + const style = this.styles; + + const fgColor = style.dialogForeground ? `${style.dialogForeground}` : null; + const bgColor = style.dialogBackground ? `${style.dialogBackground}` : null; + const shadowColor = style.dialogShadow ? `0 0px 8px ${style.dialogShadow}` : null; + const border = style.dialogBorder ? `1px solid ${style.dialogBorder}` : null; + + if (this.element) { + this.element.style.color = fgColor; + this.element.style.backgroundColor = bgColor; + this.element.style.boxShadow = shadowColor; + this.element.style.border = border; + + if (this.buttonGroup) { + this.buttonGroup.buttons.forEach(button => button.style(style)); + } + } + } + } + + style(style: IDialogStyles): void { + this.styles = style; + this.applyStyles(); + } + + dispose(): void { + super.dispose(); + if (this.modal) { + removeNode(this.modal); + this.modal = undefined; + } + + if (this.focusToReturn && isAncestor(this.focusToReturn, document.body)) { + this.focusToReturn.focus(); + this.focusToReturn = undefined; + } + } + + private rearrangeButtons(buttons: Array, cancelId: number | undefined): ButtonMapEntry[] { + const buttonMap: ButtonMapEntry[] = []; + // Maps each button to its current label and old index so that when we move them around it's not a problem + buttons.forEach((button, index) => { + buttonMap.push({ label: button, index: index }); + }); + + // macOS/linux: reverse button order + if (isMacintosh || isLinux) { + if (cancelId !== undefined) { + const cancelButton = buttonMap.splice(cancelId, 1)[0]; + buttonMap.reverse(); + buttonMap.splice(buttonMap.length - 1, 0, cancelButton); + } + } + + return buttonMap; + } +} \ No newline at end of file diff --git a/src/vs/base/browser/ui/dialog/error-dark.svg b/src/vs/base/browser/ui/dialog/error-dark.svg new file mode 100644 index 00000000000..efdc5f2ae2d --- /dev/null +++ b/src/vs/base/browser/ui/dialog/error-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/dialog/error-light.svg b/src/vs/base/browser/ui/dialog/error-light.svg new file mode 100644 index 00000000000..d646c72c740 --- /dev/null +++ b/src/vs/base/browser/ui/dialog/error-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/dialog/info-dark.svg b/src/vs/base/browser/ui/dialog/info-dark.svg new file mode 100644 index 00000000000..bb851afdfe5 --- /dev/null +++ b/src/vs/base/browser/ui/dialog/info-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/dialog/info-light.svg b/src/vs/base/browser/ui/dialog/info-light.svg new file mode 100644 index 00000000000..6faf670cccc --- /dev/null +++ b/src/vs/base/browser/ui/dialog/info-light.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/vs/base/browser/ui/dialog/pending-dark.svg b/src/vs/base/browser/ui/dialog/pending-dark.svg new file mode 100644 index 00000000000..5f388381162 --- /dev/null +++ b/src/vs/base/browser/ui/dialog/pending-dark.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/src/vs/base/browser/ui/dialog/pending-hc.svg b/src/vs/base/browser/ui/dialog/pending-hc.svg new file mode 100644 index 00000000000..c6d0ec7e29f --- /dev/null +++ b/src/vs/base/browser/ui/dialog/pending-hc.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/src/vs/base/browser/ui/dialog/pending.svg b/src/vs/base/browser/ui/dialog/pending.svg new file mode 100644 index 00000000000..47ce444bb24 --- /dev/null +++ b/src/vs/base/browser/ui/dialog/pending.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/src/vs/base/browser/ui/dialog/warning-dark.svg b/src/vs/base/browser/ui/dialog/warning-dark.svg new file mode 100644 index 00000000000..a267963e585 --- /dev/null +++ b/src/vs/base/browser/ui/dialog/warning-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/dialog/warning-light.svg b/src/vs/base/browser/ui/dialog/warning-light.svg new file mode 100644 index 00000000000..f2e2aa741e5 --- /dev/null +++ b/src/vs/base/browser/ui/dialog/warning-light.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/vs/base/browser/ui/dropdown/dropdown.ts b/src/vs/base/browser/ui/dropdown/dropdown.ts index 37ae1525dc3..7c984ea2163 100644 --- a/src/vs/base/browser/ui/dropdown/dropdown.ts +++ b/src/vs/base/browser/ui/dropdown/dropdown.ts @@ -6,7 +6,7 @@ import 'vs/css!./dropdown'; import { Gesture, EventType as GestureEventType } from 'vs/base/browser/touch'; import { ActionRunner, IAction, IActionRunner } from 'vs/base/common/actions'; -import { BaseActionItem, IActionItemProvider } from 'vs/base/browser/ui/actionbar/actionbar'; +import { BaseActionViewItem, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IContextViewProvider, IAnchor, AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { IMenuOptions } from 'vs/base/browser/ui/menu/menu'; @@ -29,7 +29,7 @@ export class BaseDropdown extends ActionRunner { private boxContainer?: HTMLElement; private _label?: HTMLElement; private contents?: HTMLElement; - private visible: boolean; + private visible: boolean | undefined; constructor(container: HTMLElement, options: IBaseDropdownOptions) { super(); @@ -108,6 +108,10 @@ export class BaseDropdown extends ActionRunner { this.visible = false; } + isVisible(): boolean { + return !!this.visible; + } + protected onEvent(e: Event, activeElement: HTMLElement): void { this.hide(); } @@ -192,12 +196,12 @@ export interface IContextMenuProvider { } export interface IActionProvider { - getActions(): IAction[]; + getActions(): ReadonlyArray; } export interface IDropdownMenuOptions extends IBaseDropdownOptions { contextMenuProvider: IContextMenuProvider; - actions?: IAction[]; + actions?: ReadonlyArray; actionProvider?: IActionProvider; menuClassName?: string; } @@ -205,7 +209,7 @@ export interface IDropdownMenuOptions extends IBaseDropdownOptions { export class DropdownMenu extends BaseDropdown { private _contextMenuProvider: IContextMenuProvider; private _menuOptions: IMenuOptions; - private _actions: IAction[]; + private _actions: ReadonlyArray; private actionProvider?: IActionProvider; private menuClassName: string; @@ -226,7 +230,7 @@ export class DropdownMenu extends BaseDropdown { return this._menuOptions; } - private get actions(): IAction[] { + private get actions(): ReadonlyArray { if (this.actionProvider) { return this.actionProvider.getActions(); } @@ -234,7 +238,7 @@ export class DropdownMenu extends BaseDropdown { return this._actions; } - private set actions(actions: IAction[]) { + private set actions(actions: ReadonlyArray) { this._actions = actions; } @@ -247,8 +251,8 @@ export class DropdownMenu extends BaseDropdown { getAnchor: () => this.element, getActions: () => this.actions, getActionsContext: () => this.menuOptions ? this.menuOptions.context : null, - getActionItem: action => this.menuOptions && this.menuOptions.actionItemProvider ? this.menuOptions.actionItemProvider(action) : null, - getKeyBinding: action => this.menuOptions && this.menuOptions.getKeyBinding ? this.menuOptions.getKeyBinding(action) : null, + getActionViewItem: action => this.menuOptions && this.menuOptions.actionViewItemProvider ? this.menuOptions.actionViewItemProvider(action) : undefined, + getKeyBinding: action => this.menuOptions && this.menuOptions.getKeyBinding ? this.menuOptions.getKeyBinding(action) : undefined, getMenuClassName: () => this.menuClassName, onHide: () => this.onHide(), actionRunner: this.menuOptions ? this.menuOptions.actionRunner : undefined, @@ -266,23 +270,23 @@ export class DropdownMenu extends BaseDropdown { } } -export class DropdownMenuActionItem extends BaseActionItem { +export class DropdownMenuActionViewItem extends BaseActionViewItem { private menuActionsOrProvider: any; - private dropdownMenu: DropdownMenu; + private dropdownMenu: DropdownMenu | undefined; private contextMenuProvider: IContextMenuProvider; - private actionItemProvider?: IActionItemProvider; - private keybindings?: (action: IAction) => ResolvedKeybinding; - private clazz: string; + private actionViewItemProvider?: IActionViewItemProvider; + private keybindings?: (action: IAction) => ResolvedKeybinding | undefined; + private clazz: string | undefined; private anchorAlignmentProvider: (() => AnchorAlignment) | undefined; - constructor(action: IAction, menuActions: IAction[], contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding) | undefined, clazz: string, anchorAlignmentProvider?: () => AnchorAlignment); - constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider | undefined, actionRunner: IActionRunner, keybindings: (action: IAction) => ResolvedKeybinding, clazz: string, anchorAlignmentProvider?: () => AnchorAlignment); - constructor(action: IAction, menuActionsOrProvider: any, contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider | undefined, actionRunner: IActionRunner, keybindings: (action: IAction) => ResolvedKeybinding, clazz: string, anchorAlignmentProvider?: () => AnchorAlignment) { + constructor(action: IAction, menuActions: ReadonlyArray, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment); + constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment); + constructor(action: IAction, menuActionsOrProvider: ReadonlyArray | IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment) { super(null, action); this.menuActionsOrProvider = menuActionsOrProvider; this.contextMenuProvider = contextMenuProvider; - this.actionItemProvider = actionItemProvider; + this.actionViewItemProvider = actionViewItemProvider; this.actionRunner = actionRunner; this.keybindings = keybindings; this.clazz = clazz; @@ -292,7 +296,9 @@ export class DropdownMenuActionItem extends BaseActionItem { render(container: HTMLElement): void { const labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable | null => { this.element = append(el, $('a.action-label.icon')); - addClasses(this.element, this.clazz); + if (this.clazz) { + addClasses(this.element, this.clazz); + } this.element.tabIndex = 0; this.element.setAttribute('role', 'button'); @@ -317,7 +323,7 @@ export class DropdownMenuActionItem extends BaseActionItem { this.dropdownMenu = this._register(new DropdownMenu(container, options)); this.dropdownMenu.menuOptions = { - actionItemProvider: this.actionItemProvider, + actionViewItemProvider: this.actionViewItemProvider, actionRunner: this.actionRunner, getKeyBinding: this.keybindings, context: this._context diff --git a/src/vs/base/browser/ui/findinput/case-sensitive-dark.svg b/src/vs/base/browser/ui/findinput/case-sensitive-dark.svg index ae540172027..40c9ed3262c 100644 --- a/src/vs/base/browser/ui/findinput/case-sensitive-dark.svg +++ b/src/vs/base/browser/ui/findinput/case-sensitive-dark.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/src/vs/base/browser/ui/findinput/case-sensitive-hc.svg b/src/vs/base/browser/ui/findinput/case-sensitive-hc.svg new file mode 100644 index 00000000000..82501418dae --- /dev/null +++ b/src/vs/base/browser/ui/findinput/case-sensitive-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/findinput/case-sensitive-light.svg b/src/vs/base/browser/ui/findinput/case-sensitive-light.svg new file mode 100644 index 00000000000..aa1dbd353e4 --- /dev/null +++ b/src/vs/base/browser/ui/findinput/case-sensitive-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/findinput/case-sensitive.svg b/src/vs/base/browser/ui/findinput/case-sensitive.svg deleted file mode 100644 index 1f3b1a2c57e..00000000000 --- a/src/vs/base/browser/ui/findinput/case-sensitive.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/findinput/findInput.ts b/src/vs/base/browser/ui/findinput/findInput.ts index 8688e319cb7..2a2964beeef 100644 --- a/src/vs/base/browser/ui/findinput/findInput.ts +++ b/src/vs/base/browser/ui/findinput/findInput.ts @@ -32,7 +32,8 @@ export interface IFindInputOptions extends IFindInputStyles { } export interface IFindInputStyles extends IInputBoxStyles { - inputActiveOptionBorder?: Color | null; + inputActiveOptionBorder?: Color; + inputActiveOptionBackground?: Color; } const NLS_DEFAULT_LABEL = nls.localize('defaultLabel', "input"); @@ -42,26 +43,26 @@ export class FindInput extends Widget { static readonly OPTION_CHANGE: string = 'optionChange'; private contextViewProvider: IContextViewProvider; - private width: number; private placeholder: string; private validation?: IInputValidator; private label: string; private fixFocusOnOptionClickEnabled = true; - private inputActiveOptionBorder?: Color | null; - private inputBackground?: Color | null; - private inputForeground?: Color | null; - private inputBorder?: Color | null; + private inputActiveOptionBorder?: Color; + private inputActiveOptionBackground?: Color; + private inputBackground?: Color; + private inputForeground?: Color; + private inputBorder?: Color; - private inputValidationInfoBorder?: Color | null; - private inputValidationInfoBackground?: Color | null; - private inputValidationInfoForeground?: Color | null; - private inputValidationWarningBorder?: Color | null; - private inputValidationWarningBackground?: Color | null; - private inputValidationWarningForeground?: Color | null; - private inputValidationErrorBorder?: Color | null; - private inputValidationErrorBackground?: Color | null; - private inputValidationErrorForeground?: Color | null; + private inputValidationInfoBorder?: Color; + private inputValidationInfoBackground?: Color; + private inputValidationInfoForeground?: Color; + private inputValidationWarningBorder?: Color; + private inputValidationWarningBackground?: Color; + private inputValidationWarningForeground?: Color; + private inputValidationErrorBorder?: Color; + private inputValidationErrorBackground?: Color; + private inputValidationErrorForeground?: Color; private regex: RegexCheckbox; private wholeWords: WholeWordsCheckbox; @@ -93,12 +94,12 @@ export class FindInput extends Widget { constructor(parent: HTMLElement | null, contextViewProvider: IContextViewProvider, private readonly _showOptionButtons: boolean, options: IFindInputOptions) { super(); this.contextViewProvider = contextViewProvider; - this.width = options.width || 100; this.placeholder = options.placeholder || ''; this.validation = options.validation; this.label = options.label || NLS_DEFAULT_LABEL; this.inputActiveOptionBorder = options.inputActiveOptionBorder; + this.inputActiveOptionBackground = options.inputActiveOptionBackground; this.inputBackground = options.inputBackground; this.inputForeground = options.inputForeground; this.inputBorder = options.inputBorder; @@ -113,7 +114,130 @@ export class FindInput extends Widget { this.inputValidationErrorBackground = options.inputValidationErrorBackground; this.inputValidationErrorForeground = options.inputValidationErrorForeground; - this.buildDomNode(options.appendCaseSensitiveLabel || '', options.appendWholeWordsLabel || '', options.appendRegexLabel || '', options.history || [], !!options.flexibleHeight); + const appendCaseSensitiveLabel = options.appendCaseSensitiveLabel || ''; + const appendWholeWordsLabel = options.appendWholeWordsLabel || ''; + const appendRegexLabel = options.appendRegexLabel || ''; + const history = options.history || []; + const flexibleHeight = !!options.flexibleHeight; + + this.domNode = document.createElement('div'); + dom.addClass(this.domNode, 'monaco-findInput'); + + this.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, { + placeholder: this.placeholder || '', + ariaLabel: this.label || '', + validationOptions: { + validation: this.validation + }, + inputBackground: this.inputBackground, + inputForeground: this.inputForeground, + inputBorder: this.inputBorder, + inputValidationInfoBackground: this.inputValidationInfoBackground, + inputValidationInfoForeground: this.inputValidationInfoForeground, + inputValidationInfoBorder: this.inputValidationInfoBorder, + inputValidationWarningBackground: this.inputValidationWarningBackground, + inputValidationWarningForeground: this.inputValidationWarningForeground, + inputValidationWarningBorder: this.inputValidationWarningBorder, + inputValidationErrorBackground: this.inputValidationErrorBackground, + inputValidationErrorForeground: this.inputValidationErrorForeground, + inputValidationErrorBorder: this.inputValidationErrorBorder, + history, + flexibleHeight + })); + + this.regex = this._register(new RegexCheckbox({ + appendTitle: appendRegexLabel, + isChecked: false, + inputActiveOptionBorder: this.inputActiveOptionBorder, + inputActiveOptionBackground: this.inputActiveOptionBackground + })); + this._register(this.regex.onChange(viaKeyboard => { + this._onDidOptionChange.fire(viaKeyboard); + if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { + this.inputBox.focus(); + } + this.validate(); + })); + this._register(this.regex.onKeyDown(e => { + this._onRegexKeyDown.fire(e); + })); + + this.wholeWords = this._register(new WholeWordsCheckbox({ + appendTitle: appendWholeWordsLabel, + isChecked: false, + inputActiveOptionBorder: this.inputActiveOptionBorder, + inputActiveOptionBackground: this.inputActiveOptionBackground + })); + this._register(this.wholeWords.onChange(viaKeyboard => { + this._onDidOptionChange.fire(viaKeyboard); + if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { + this.inputBox.focus(); + } + this.validate(); + })); + + this.caseSensitive = this._register(new CaseSensitiveCheckbox({ + appendTitle: appendCaseSensitiveLabel, + isChecked: false, + inputActiveOptionBorder: this.inputActiveOptionBorder, + inputActiveOptionBackground: this.inputActiveOptionBackground + })); + this._register(this.caseSensitive.onChange(viaKeyboard => { + this._onDidOptionChange.fire(viaKeyboard); + if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { + this.inputBox.focus(); + } + this.validate(); + })); + this._register(this.caseSensitive.onKeyDown(e => { + this._onCaseSensitiveKeyDown.fire(e); + })); + + if (this._showOptionButtons) { + const paddingRight = (this.caseSensitive.width() + this.wholeWords.width() + this.regex.width()) + 'px'; + this.inputBox.inputElement.style.paddingRight = paddingRight; + if (this.inputBox.mirrorElement) { + this.inputBox.mirrorElement.style.paddingRight = paddingRight; + } + } + + // Arrow-Key support to navigate between options + let indexes = [this.caseSensitive.domNode, this.wholeWords.domNode, this.regex.domNode]; + this.onkeydown(this.domNode, (event: IKeyboardEvent) => { + if (event.equals(KeyCode.LeftArrow) || event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Escape)) { + let index = indexes.indexOf(document.activeElement); + if (index >= 0) { + let newIndex: number = -1; + if (event.equals(KeyCode.RightArrow)) { + newIndex = (index + 1) % indexes.length; + } else if (event.equals(KeyCode.LeftArrow)) { + if (index === 0) { + newIndex = indexes.length - 1; + } else { + newIndex = index - 1; + } + } + + if (event.equals(KeyCode.Escape)) { + indexes[index].blur(); + } else if (newIndex >= 0) { + indexes[newIndex].focus(); + } + + dom.EventHelper.stop(event, true); + } + } + }); + + + let controls = document.createElement('div'); + controls.className = 'controls'; + controls.style.display = this._showOptionButtons ? 'block' : 'none'; + controls.appendChild(this.caseSensitive.domNode); + controls.appendChild(this.wholeWords.domNode); + controls.appendChild(this.regex.domNode); + + this.domNode.appendChild(controls); if (parent) { parent.appendChild(this.domNode); @@ -159,13 +283,6 @@ export class FindInput extends Widget { this.focus(); } - public setWidth(newWidth: number): void { - this.width = newWidth; - this.domNode.style.width = this.width + 'px'; - this.contextViewProvider.layout(); - this.setInputWidth(); - } - public getValue(): string { return this.inputBox.value; } @@ -182,6 +299,7 @@ export class FindInput extends Widget { public style(styles: IFindInputStyles): void { this.inputActiveOptionBorder = styles.inputActiveOptionBorder; + this.inputActiveOptionBackground = styles.inputActiveOptionBackground; this.inputBackground = styles.inputBackground; this.inputForeground = styles.inputForeground; this.inputBorder = styles.inputBorder; @@ -202,7 +320,8 @@ export class FindInput extends Widget { protected applyStyles(): void { if (this.domNode) { const checkBoxStyles: ICheckboxStyles = { - inputActiveOptionBorder: this.inputActiveOptionBorder || undefined, + inputActiveOptionBorder: this.inputActiveOptionBorder, + inputActiveOptionBackground: this.inputActiveOptionBackground, }; this.regex.style(checkBoxStyles); this.wholeWords.style(checkBoxStyles); @@ -240,7 +359,6 @@ export class FindInput extends Widget { public setCaseSensitive(value: boolean): void { this.caseSensitive.checked = value; - this.setInputWidth(); } public getWholeWords(): boolean { @@ -249,7 +367,6 @@ export class FindInput extends Widget { public setWholeWords(value: boolean): void { this.wholeWords.checked = value; - this.setInputWidth(); } public getRegex(): boolean { @@ -258,7 +375,6 @@ export class FindInput extends Widget { public setRegex(value: boolean): void { this.regex.checked = value; - this.setInputWidth(); this.validate(); } @@ -277,127 +393,6 @@ export class FindInput extends Widget { dom.addClass(this.domNode, 'highlight-' + (this._lastHighlightFindOptions)); } - private setInputWidth(): void { - let w = this.width - this.caseSensitive.width() - this.wholeWords.width() - this.regex.width(); - this.inputBox.width = w; - this.inputBox.layout(); - } - - private buildDomNode(appendCaseSensitiveLabel: string, appendWholeWordsLabel: string, appendRegexLabel: string, history: string[], flexibleHeight: boolean): void { - this.domNode = document.createElement('div'); - this.domNode.style.width = this.width + 'px'; - dom.addClass(this.domNode, 'monaco-findInput'); - - this.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, { - placeholder: this.placeholder || '', - ariaLabel: this.label || '', - validationOptions: { - validation: this.validation - }, - inputBackground: this.inputBackground, - inputForeground: this.inputForeground, - inputBorder: this.inputBorder, - inputValidationInfoBackground: this.inputValidationInfoBackground, - inputValidationInfoForeground: this.inputValidationInfoForeground, - inputValidationInfoBorder: this.inputValidationInfoBorder, - inputValidationWarningBackground: this.inputValidationWarningBackground, - inputValidationWarningForeground: this.inputValidationWarningForeground, - inputValidationWarningBorder: this.inputValidationWarningBorder, - inputValidationErrorBackground: this.inputValidationErrorBackground, - inputValidationErrorForeground: this.inputValidationErrorForeground, - inputValidationErrorBorder: this.inputValidationErrorBorder, - history, - flexibleHeight - })); - - this.regex = this._register(new RegexCheckbox({ - appendTitle: appendRegexLabel, - isChecked: false, - inputActiveOptionBorder: this.inputActiveOptionBorder || undefined - })); - this._register(this.regex.onChange(viaKeyboard => { - this._onDidOptionChange.fire(viaKeyboard); - if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { - this.inputBox.focus(); - } - this.setInputWidth(); - this.validate(); - })); - this._register(this.regex.onKeyDown(e => { - this._onRegexKeyDown.fire(e); - })); - - this.wholeWords = this._register(new WholeWordsCheckbox({ - appendTitle: appendWholeWordsLabel, - isChecked: false, - inputActiveOptionBorder: this.inputActiveOptionBorder || undefined - })); - this._register(this.wholeWords.onChange(viaKeyboard => { - this._onDidOptionChange.fire(viaKeyboard); - if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { - this.inputBox.focus(); - } - this.setInputWidth(); - this.validate(); - })); - - this.caseSensitive = this._register(new CaseSensitiveCheckbox({ - appendTitle: appendCaseSensitiveLabel, - isChecked: false, - inputActiveOptionBorder: this.inputActiveOptionBorder || undefined - })); - this._register(this.caseSensitive.onChange(viaKeyboard => { - this._onDidOptionChange.fire(viaKeyboard); - if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { - this.inputBox.focus(); - } - this.setInputWidth(); - this.validate(); - })); - this._register(this.caseSensitive.onKeyDown(e => { - this._onCaseSensitiveKeyDown.fire(e); - })); - - // Arrow-Key support to navigate between options - let indexes = [this.caseSensitive.domNode, this.wholeWords.domNode, this.regex.domNode]; - this.onkeydown(this.domNode, (event: IKeyboardEvent) => { - if (event.equals(KeyCode.LeftArrow) || event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Escape)) { - let index = indexes.indexOf(document.activeElement); - if (index >= 0) { - let newIndex: number = -1; - if (event.equals(KeyCode.RightArrow)) { - newIndex = (index + 1) % indexes.length; - } else if (event.equals(KeyCode.LeftArrow)) { - if (index === 0) { - newIndex = indexes.length - 1; - } else { - newIndex = index - 1; - } - } - - if (event.equals(KeyCode.Escape)) { - indexes[index].blur(); - } else if (newIndex >= 0) { - indexes[newIndex].focus(); - } - - dom.EventHelper.stop(event, true); - } - } - }); - - this.setInputWidth(); - - let controls = document.createElement('div'); - controls.className = 'controls'; - controls.style.display = this._showOptionButtons ? 'block' : 'none'; - controls.appendChild(this.caseSensitive.domNode); - controls.appendChild(this.wholeWords.domNode); - controls.appendChild(this.regex.domNode); - - this.domNode.appendChild(controls); - } - public validate(): void { if (this.inputBox) { this.inputBox.validate(); diff --git a/src/vs/base/browser/ui/findinput/findInputCheckboxes.css b/src/vs/base/browser/ui/findinput/findInputCheckboxes.css index 37e890d7f89..c72a7350f63 100644 --- a/src/vs/base/browser/ui/findinput/findInputCheckboxes.css +++ b/src/vs/base/browser/ui/findinput/findInputCheckboxes.css @@ -4,28 +4,53 @@ *--------------------------------------------------------------------------------------------*/ .vs .monaco-custom-checkbox.monaco-case-sensitive { - background: url('case-sensitive.svg') center center no-repeat; + background: url('case-sensitive-light.svg') center center no-repeat; } -.hc-black .monaco-custom-checkbox.monaco-case-sensitive, -.hc-black .monaco-custom-checkbox.monaco-case-sensitive:hover, + .vs-dark .monaco-custom-checkbox.monaco-case-sensitive { background: url('case-sensitive-dark.svg') center center no-repeat; } -.vs .monaco-custom-checkbox.monaco-whole-word { - background: url('whole-word.svg') center center no-repeat; +.hc-black .monaco-custom-checkbox.monaco-case-sensitive, +.hc-black .monaco-custom-checkbox.monaco-case-sensitive:hover { + background: url('case-sensitive-hc.svg') center center no-repeat; } -.hc-black .monaco-custom-checkbox.monaco-whole-word, -.hc-black .monaco-custom-checkbox.monaco-whole-word:hover, + +.vs .monaco-custom-checkbox.monaco-preserve-case { + background: url('preserve-case-light.svg') center center no-repeat; +} + +.vs-dark .monaco-custom-checkbox.monaco-preserve-case { + background: url('preserve-case-dark.svg') center center no-repeat; +} + +.hc-black .monaco-custom-checkbox.monaco-preserve-case, +.hc-black .monaco-custom-checkbox.monaco-preserve-case:hover { + background: url('preserve-case-hc.svg') center center no-repeat; +} + +.vs .monaco-custom-checkbox.monaco-whole-word { + background: url('whole-word-light.svg') center center no-repeat; +} + .vs-dark .monaco-custom-checkbox.monaco-whole-word { background: url('whole-word-dark.svg') center center no-repeat; } -.vs .monaco-custom-checkbox.monaco-regex { - background: url('regex.svg') center center no-repeat; +.hc-black .monaco-custom-checkbox.monaco-whole-word, +.hc-black .monaco-custom-checkbox.monaco-whole-word:hover { + background: url('whole-word-hc.svg') center center no-repeat; } -.hc-black .monaco-custom-checkbox.monaco-regex, -.hc-black .monaco-custom-checkbox.monaco-regex:hover, + +.vs .monaco-custom-checkbox.monaco-regex { + background: url('regex-light.svg') center center no-repeat; +} + .vs-dark .monaco-custom-checkbox.monaco-regex { background: url('regex-dark.svg') center center no-repeat; } + +.hc-black .monaco-custom-checkbox.monaco-regex, +.hc-black .monaco-custom-checkbox.monaco-regex:hover { + background: url('regex-hc.svg') center center no-repeat; +} diff --git a/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts b/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts index 62451f1a4b8..effef734a8c 100644 --- a/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts +++ b/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts @@ -12,6 +12,7 @@ export interface IFindInputCheckboxOpts { readonly appendTitle: string; readonly isChecked: boolean; readonly inputActiveOptionBorder?: Color; + readonly inputActiveOptionBackground?: Color; } const NLS_CASE_SENSITIVE_CHECKBOX_LABEL = nls.localize('caseDescription', "Match Case"); @@ -24,7 +25,8 @@ export class CaseSensitiveCheckbox extends Checkbox { actionClassName: 'monaco-case-sensitive', title: NLS_CASE_SENSITIVE_CHECKBOX_LABEL + opts.appendTitle, isChecked: opts.isChecked, - inputActiveOptionBorder: opts.inputActiveOptionBorder + inputActiveOptionBorder: opts.inputActiveOptionBorder, + inputActiveOptionBackground: opts.inputActiveOptionBackground }); } } @@ -35,7 +37,8 @@ export class WholeWordsCheckbox extends Checkbox { actionClassName: 'monaco-whole-word', title: NLS_WHOLE_WORD_CHECKBOX_LABEL + opts.appendTitle, isChecked: opts.isChecked, - inputActiveOptionBorder: opts.inputActiveOptionBorder + inputActiveOptionBorder: opts.inputActiveOptionBorder, + inputActiveOptionBackground: opts.inputActiveOptionBackground }); } } @@ -46,7 +49,8 @@ export class RegexCheckbox extends Checkbox { actionClassName: 'monaco-regex', title: NLS_REGEX_CHECKBOX_LABEL + opts.appendTitle, isChecked: opts.isChecked, - inputActiveOptionBorder: opts.inputActiveOptionBorder + inputActiveOptionBorder: opts.inputActiveOptionBorder, + inputActiveOptionBackground: opts.inputActiveOptionBackground }); } } diff --git a/src/vs/base/browser/ui/findinput/preserve-case-dark.svg b/src/vs/base/browser/ui/findinput/preserve-case-dark.svg new file mode 100644 index 00000000000..1c87e34716e --- /dev/null +++ b/src/vs/base/browser/ui/findinput/preserve-case-dark.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/vs/base/browser/ui/findinput/preserve-case-hc.svg b/src/vs/base/browser/ui/findinput/preserve-case-hc.svg new file mode 100644 index 00000000000..f316948bb9c --- /dev/null +++ b/src/vs/base/browser/ui/findinput/preserve-case-hc.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/vs/base/browser/ui/findinput/preserve-case-light.svg b/src/vs/base/browser/ui/findinput/preserve-case-light.svg new file mode 100644 index 00000000000..83954b66520 --- /dev/null +++ b/src/vs/base/browser/ui/findinput/preserve-case-light.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/vs/base/browser/ui/findinput/regex-dark.svg b/src/vs/base/browser/ui/findinput/regex-dark.svg index c303032e6a9..cf43e9d952e 100644 --- a/src/vs/base/browser/ui/findinput/regex-dark.svg +++ b/src/vs/base/browser/ui/findinput/regex-dark.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/src/vs/base/browser/ui/findinput/regex-hc.svg b/src/vs/base/browser/ui/findinput/regex-hc.svg new file mode 100644 index 00000000000..116c547d15f --- /dev/null +++ b/src/vs/base/browser/ui/findinput/regex-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/findinput/regex-light.svg b/src/vs/base/browser/ui/findinput/regex-light.svg new file mode 100644 index 00000000000..b329c104fa2 --- /dev/null +++ b/src/vs/base/browser/ui/findinput/regex-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/findinput/whole-word-dark.svg b/src/vs/base/browser/ui/findinput/whole-word-dark.svg index d18e144f318..6c38eb215d3 100644 --- a/src/vs/base/browser/ui/findinput/whole-word-dark.svg +++ b/src/vs/base/browser/ui/findinput/whole-word-dark.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/src/vs/base/browser/ui/findinput/whole-word-hc.svg b/src/vs/base/browser/ui/findinput/whole-word-hc.svg new file mode 100644 index 00000000000..fc1ff43268b --- /dev/null +++ b/src/vs/base/browser/ui/findinput/whole-word-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/findinput/whole-word-light.svg b/src/vs/base/browser/ui/findinput/whole-word-light.svg new file mode 100644 index 00000000000..345e65b2a5c --- /dev/null +++ b/src/vs/base/browser/ui/findinput/whole-word-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/findinput/whole-word.svg b/src/vs/base/browser/ui/findinput/whole-word.svg deleted file mode 100644 index 8244d95abdf..00000000000 --- a/src/vs/base/browser/ui/findinput/whole-word.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/grid/grid.ts b/src/vs/base/browser/ui/grid/grid.ts index 336329a05e2..eb8476e1b8b 100644 --- a/src/vs/base/browser/ui/grid/grid.ts +++ b/src/vs/base/browser/ui/grid/grid.ts @@ -5,12 +5,13 @@ import 'vs/css!./gridview'; import { Orientation } from 'vs/base/browser/ui/sash/sash'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { Disposable } from 'vs/base/common/lifecycle'; import { tail2 as tail, equals } from 'vs/base/common/arrays'; -import { orthogonal, IView, GridView, Sizing as GridViewSizing, Box, IGridViewStyles } from './gridview'; +import { orthogonal, IView as IGridViewView, GridView, Sizing as GridViewSizing, Box, IGridViewStyles, IViewSize, ILayoutController, LayoutController } from './gridview'; import { Event } from 'vs/base/common/event'; +import { InvisibleSizing } from 'vs/base/browser/ui/splitview/splitview'; -export { Orientation } from './gridview'; +export { Orientation, Sizing as GridViewSizing, IViewSize, orthogonal, LayoutPriority } from './gridview'; export const enum Direction { Up, @@ -28,9 +29,15 @@ function oppositeDirection(direction: Direction): Direction { } } +export interface IView extends IGridViewView { + readonly preferredHeight?: number; + readonly preferredWidth?: number; +} + export interface GridLeafNode { readonly view: T; readonly box: Box; + readonly cachedVisibleSize: number | undefined; } export interface GridBranchNode { @@ -115,10 +122,6 @@ function getDirectionOrientation(direction: Direction): Orientation { return direction === Direction.Up || direction === Direction.Down ? Orientation.VERTICAL : Orientation.HORIZONTAL; } -function getSize(dimensions: { width: number; height: number; }, orientation: Orientation) { - return orientation === Orientation.HORIZONTAL ? dimensions.width : dimensions.height; -} - export function getRelativeLocation(rootOrientation: Orientation, location: number[], direction: Direction): number[] { const orientation = getLocationOrientation(rootOrientation, location); const directionOrientation = getDirectionOrientation(direction); @@ -177,23 +180,30 @@ function getGridLocation(element: HTMLElement): number[] { return [...getGridLocation(ancestor), index]; } -export const enum Sizing { - Distribute = 'distribute', - Split = 'split' +export type DistributeSizing = { type: 'distribute' }; +export type SplitSizing = { type: 'split' }; +export type InvisibleSizing = { type: 'invisible', cachedVisibleSize: number }; +export type Sizing = DistributeSizing | SplitSizing | InvisibleSizing; + +export namespace Sizing { + export const Distribute: DistributeSizing = { type: 'distribute' }; + export const Split: SplitSizing = { type: 'split' }; + export function Invisible(cachedVisibleSize: number): InvisibleSizing { return { type: 'invisible', cachedVisibleSize }; } } export interface IGridStyles extends IGridViewStyles { } export interface IGridOptions { - styles?: IGridStyles; + readonly styles?: IGridStyles; + readonly proportionalLayout?: boolean; + readonly firstViewVisibleCachedSize?: number; + readonly layoutController?: ILayoutController; } -export class Grid implements IDisposable { +export class Grid extends Disposable { protected gridview: GridView; private views = new Map(); - private disposables: IDisposable[] = []; - get orientation(): Orientation { return this.gridview.orientation; } set orientation(orientation: Orientation) { this.gridview.orientation = orientation; } @@ -208,15 +218,20 @@ export class Grid implements IDisposable { get element(): HTMLElement { return this.gridview.element; } - sashResetSizing: Sizing = Sizing.Distribute; + private didLayout = false; constructor(view: T, options: IGridOptions = {}) { + super(); this.gridview = new GridView(options); - this.disposables.push(this.gridview); + this._register(this.gridview); - this.gridview.onDidSashReset(this.doResetViewSize, this, this.disposables); + this._register(this.gridview.onDidSashReset(this.onDidSashReset, this)); - this._addView(view, 0, [0]); + const size: number | GridViewSizing = typeof options.firstViewVisibleCachedSize === 'number' + ? GridViewSizing.Invisible(options.firstViewVisibleCachedSize) + : 0; + + this._addView(view, size, [0]); } style(styles: IGridStyles): void { @@ -225,6 +240,11 @@ export class Grid implements IDisposable { layout(width: number, height: number): void { this.gridview.layout(width, height); + this.didLayout = true; + } + + hasView(view: T): boolean { + return this.views.has(view); } addView(newView: T, size: number | Sizing, referenceView: T, direction: Direction): void { @@ -243,10 +263,12 @@ export class Grid implements IDisposable { let viewSize: number | GridViewSizing; - if (size === Sizing.Split) { + if (typeof size === 'number') { + viewSize = size; + } else if (size.type === 'split') { const [, index] = tail(referenceLocation); viewSize = GridViewSizing.Split(index); - } else if (size === Sizing.Distribute) { + } else if (size.type === 'distribute') { viewSize = GridViewSizing.Distribute; } else { viewSize = size; @@ -255,7 +277,7 @@ export class Grid implements IDisposable { this._addView(newView, viewSize, location); } - protected _addView(newView: T, size: number | GridViewSizing, location): void { + protected _addView(newView: T, size: number | GridViewSizing, location: number[]): void { this.views.set(newView, newView.element); this.gridview.addView(newView, size, location); } @@ -266,7 +288,7 @@ export class Grid implements IDisposable { } const location = this.getViewLocation(view); - this.gridview.removeView(location, sizing === Sizing.Distribute ? GridViewSizing.Distribute : undefined); + this.gridview.removeView(location, (sizing && sizing.type === 'distribute') ? GridViewSizing.Distribute : undefined); this.views.delete(view); } @@ -292,19 +314,12 @@ export class Grid implements IDisposable { return this.gridview.swapViews(fromLocation, toLocation); } - resizeView(view: T, size: number): void { + resizeView(view: T, size: IViewSize): void { const location = this.getViewLocation(view); return this.gridview.resizeView(location, size); } - getViewSize(view: T): number { - const location = this.getViewLocation(view); - const viewSize = this.gridview.getViewSize(location); - return getLocationOrientation(this.orientation, location) === Orientation.HORIZONTAL ? viewSize.width : viewSize.height; - } - - // TODO@joao cleanup - getViewSize2(view: T): { width: number; height: number; } { + getViewSize(view: T): IViewSize { const location = this.getViewLocation(view); return this.gridview.getViewSize(location); } @@ -318,11 +333,25 @@ export class Grid implements IDisposable { this.gridview.distributeViewSizes(); } + isViewVisible(view: T): boolean { + const location = this.getViewLocation(view); + return this.gridview.isViewVisible(location); + } + + setViewVisible(view: T, visible: boolean): void { + const location = this.getViewLocation(view); + this.gridview.setViewVisible(location, visible); + } + getViews(): GridBranchNode { - return this.gridview.getViews() as GridBranchNode; + return this.gridview.getView() as GridBranchNode; } getNeighborViews(view: T, direction: Direction, wrap: boolean = false): T[] { + if (!this.didLayout) { + throw new Error('Can\'t call getNeighborViews before first layout'); + } + const location = this.getViewLocation(view); const root = this.getViews(); const node = getGridNode(root, location); @@ -354,23 +383,37 @@ export class Grid implements IDisposable { return getGridLocation(element); } - private doResetViewSize(location: number[]): void { - if (this.sashResetSizing === Sizing.Split) { - const orientation = getLocationOrientation(this.orientation, location); - const firstViewSize = getSize(this.gridview.getViewSize(location), orientation); - const [parentLocation, index] = tail(location); - const secondViewSize = getSize(this.gridview.getViewSize([...parentLocation, index + 1]), orientation); - const totalSize = firstViewSize + secondViewSize; - this.gridview.resizeView(location, Math.floor(totalSize / 2)); + private onDidSashReset(location: number[]): void { + const resizeToPreferredSize = (location: number[]): boolean => { + const node = this.gridview.getView(location) as GridNode; - } else { - const [parentLocation,] = tail(location); - this.gridview.distributeViewSizes(parentLocation); + if (isGridBranchNode(node)) { + return false; + } + + const direction = getLocationOrientation(this.orientation, location); + const size = direction === Orientation.HORIZONTAL ? node.view.preferredWidth : node.view.preferredHeight; + + if (typeof size !== 'number') { + return false; + } + + const viewSize = direction === Orientation.HORIZONTAL ? { width: Math.round(size) } : { height: Math.round(size) }; + this.gridview.resizeView(location, viewSize); + return true; + }; + + if (resizeToPreferredSize(location)) { + return; } - } - dispose(): void { - this.disposables = dispose(this.disposables); + const [parentLocation, index] = tail(location); + + if (resizeToPreferredSize([...parentLocation, index + 1])) { + return; + } + + this.gridview.distributeViewSizes(parentLocation); } } @@ -392,6 +435,7 @@ export interface ISerializedLeafNode { type: 'leaf'; data: object | null; size: number; + visible?: boolean; } export interface ISerializedBranchNode { @@ -415,6 +459,10 @@ export class SerializableGrid extends Grid { const size = orientation === Orientation.VERTICAL ? node.box.width : node.box.height; if (!isGridBranchNode(node)) { + if (typeof node.cachedVisibleSize === 'number') { + return { type: 'leaf', data: node.view.toJSON(), size: node.cachedVisibleSize, visible: false }; + } + return { type: 'leaf', data: node.view.toJSON(), size }; } @@ -439,25 +487,26 @@ export class SerializableGrid extends Grid { throw new Error('Invalid JSON: \'size\' property of node must be a number.'); } + const childSize = child.type === 'leaf' && child.visible === false ? 0 : child.size; const childBox: Box = orientation === Orientation.HORIZONTAL - ? { top: box.top, left: box.left + offset, width: child.size, height: box.height } - : { top: box.top + offset, left: box.left, width: box.width, height: child.size }; + ? { top: box.top, left: box.left + offset, width: childSize, height: box.height } + : { top: box.top + offset, left: box.left, width: box.width, height: childSize }; children.push(SerializableGrid.deserializeNode(child, orthogonal(orientation), childBox, deserializer)); - offset += child.size; + offset += childSize; } return { children, box }; } else if (json.type === 'leaf') { - const view = deserializer.fromJSON(json.data) as T; - return { view, box }; + const view: T = deserializer.fromJSON(json.data); + return { view, box, cachedVisibleSize: json.visible === false ? json.size : undefined }; } throw new Error('Invalid JSON: \'type\' property must be either \'branch\' or \'leaf\'.'); } - private static getFirstLeaf(node: GridNode): GridLeafNode | undefined { + private static getFirstLeaf(node: GridNode): GridLeafNode { if (!isGridBranchNode(node)) { return node; } @@ -474,9 +523,9 @@ export class SerializableGrid extends Grid { throw new Error('Invalid JSON: \'height\' property must be a number.'); } - const orientation = json.orientation as Orientation; - const width = json.width as number; - const height = json.height as number; + const orientation = json.orientation; + const width = json.width; + const height = json.height; const box: Box = { top: 0, left: 0, width, height }; const root = SerializableGrid.deserializeNode(json.root, orientation, box, deserializer) as GridBranchNode; @@ -486,11 +535,19 @@ export class SerializableGrid extends Grid { throw new Error('Invalid serialized state, first leaf not found'); } + const layoutController = new LayoutController(false); + options = { ...options, layoutController }; + + if (typeof firstLeaf.cachedVisibleSize === 'number') { + options = { ...options, firstViewVisibleCachedSize: firstLeaf.cachedVisibleSize }; + } + const result = new SerializableGrid(firstLeaf.view, options); result.orientation = orientation; result.restoreViews(firstLeaf.view, orientation, root); result.initialLayoutContext = { width, height, root }; + layoutController.isLayoutEnabled = true; return result; } @@ -535,13 +592,16 @@ export class SerializableGrid extends Grid { const firstLeaves = node.children.map(c => SerializableGrid.getFirstLeaf(c)); for (let i = 1; i < firstLeaves.length; i++) { - const size = orientation === Orientation.VERTICAL ? firstLeaves[i]!.box.height : firstLeaves[i]!.box.width; - this.addView(firstLeaves[i]!.view, size, referenceView, direction); - referenceView = firstLeaves[i]!.view; + const node = firstLeaves[i]; + const size: number | InvisibleSizing = typeof node.cachedVisibleSize === 'number' + ? GridViewSizing.Invisible(node.cachedVisibleSize) + : (orientation === Orientation.VERTICAL ? node.box.height : node.box.width); + this.addView(node.view, size, referenceView, direction); + referenceView = node.view; } for (let i = 0; i < node.children.length; i++) { - this.restoreViews(firstLeaves[i]!.view, orthogonal(orientation), node.children[i]); + this.restoreViews(firstLeaves[i].view, orthogonal(orientation), node.children[i]); } } @@ -561,8 +621,11 @@ export class SerializableGrid extends Grid { const childLocation = [...location, i]; if (i < node.children.length - 1) { - const size = orientation === Orientation.VERTICAL ? child.box.height : child.box.width; - this.gridview.resizeView(childLocation, Math.floor(size * scale)); + const size = orientation === Orientation.VERTICAL + ? { height: Math.floor(child.box.height * scale) } + : { width: Math.floor(child.box.width * scale) }; + + this.gridview.resizeView(childLocation, size); } this.restoreViewsSize(childLocation, child, orthogonal(orientation), widthScale, heightScale); diff --git a/src/vs/base/browser/ui/grid/gridview.ts b/src/vs/base/browser/ui/grid/gridview.ts index 73c042929c1..7ec49f3b343 100644 --- a/src/vs/base/browser/ui/grid/gridview.ts +++ b/src/vs/base/browser/ui/grid/gridview.ts @@ -15,16 +15,22 @@ import { Color } from 'vs/base/common/color'; export { Sizing, LayoutPriority } from 'vs/base/browser/ui/splitview/splitview'; export { Orientation } from 'vs/base/browser/ui/sash/sash'; +export interface IViewSize { + readonly width: number; + readonly height: number; +} + export interface IView { readonly element: HTMLElement; readonly minimumWidth: number; readonly maximumWidth: number; readonly minimumHeight: number; readonly maximumHeight: number; - readonly onDidChange: Event<{ width: number; height: number; } | undefined>; + readonly onDidChange: Event; readonly priority?: LayoutPriority; - readonly snapSize?: number; - layout(width: number, height: number): void; + readonly snap?: boolean; + layout(width: number, height: number, orientation: Orientation): void; + setVisible?(visible: boolean): void; } export function orthogonal(orientation: Orientation): Orientation { @@ -41,6 +47,7 @@ export interface Box { export interface GridLeafNode { readonly view: IView; readonly box: Box; + readonly cachedVisibleSize: number | undefined; } export interface GridBranchNode { @@ -60,9 +67,18 @@ const defaultStyles: IGridViewStyles = { separatorBorder: Color.transparent }; +export interface ILayoutController { + readonly isLayoutEnabled: boolean; +} + +export class LayoutController implements ILayoutController { + constructor(public isLayoutEnabled: boolean) { } +} + export interface IGridViewOptions { - styles?: IGridViewStyles; - proportionalLayout?: boolean; // default true + readonly styles?: IGridViewStyles; + readonly proportionalLayout?: boolean; // default true + readonly layoutController?: ILayoutController; } class BranchNode implements ISplitView, IDisposable { @@ -96,6 +112,22 @@ class BranchNode implements ISplitView, IDisposable { return Math.min(...this.children.map(c => c.maximumOrthogonalSize)); } + get priority(): LayoutPriority { + if (this.children.length === 0) { + return LayoutPriority.Normal; + } + + const priorities = this.children.map(c => typeof c.priority === 'undefined' ? LayoutPriority.Normal : c.priority); + + if (priorities.some(p => p === LayoutPriority.High)) { + return LayoutPriority.High; + } else if (priorities.some(p => p === LayoutPriority.Low)) { + return LayoutPriority.Low; + } + + return LayoutPriority.Normal; + } + get minimumOrthogonalSize(): number { return this.splitview.minimumSize; } @@ -147,7 +179,7 @@ class BranchNode implements ISplitView, IDisposable { this._orthogonalSize = orthogonalSize; this.element = $('.monaco-grid-branch-node'); - this.splitview = new SplitView(this.element, { orientation, styles }); + this.splitview = new SplitView(this.element, { orientation, styles, proportionalLayout }); this.splitview.layout(size); const onDidSashReset = Event.map(this.splitview.onDidSashReset, i => [i]); @@ -173,6 +205,12 @@ class BranchNode implements ISplitView, IDisposable { } } + setVisible(visible: boolean): void { + for (const child of this.children) { + child.setVisible(visible); + } + } + orthogonalLayout(size: number): void { this._size = size; this.splitview.layout(size); @@ -299,8 +337,32 @@ class BranchNode implements ISplitView, IDisposable { return this.splitview.getViewSize(index); } + isChildVisible(index: number): boolean { + if (index < 0 || index >= this.children.length) { + throw new Error('Invalid index'); + } + + return this.splitview.isViewVisible(index); + } + + setChildVisible(index: number, visible: boolean): void { + if (index < 0 || index >= this.children.length) { + throw new Error('Invalid index'); + } + + this.splitview.setViewVisible(index, visible); + } + + getChildCachedVisibleSize(index: number): number | undefined { + if (index < 0 || index >= this.children.length) { + throw new Error('Invalid index'); + } + + return this.splitview.getViewCachedVisibleSize(index); + } + private onDidChildrenChange(): void { - const onDidChildrenChange = Event.any(...this.children.map(c => c.onDidChange)); + const onDidChildrenChange = Event.map(Event.any(...this.children.map(c => c.onDidChange)), () => undefined); this.childrenChangeDisposable.dispose(); this.childrenChangeDisposable = onDidChildrenChange(this._onDidChange.fire, this._onDidChange); @@ -380,6 +442,9 @@ class LeafNode implements ISplitView, IDisposable { private _size: number = 0; get size(): number { return this._size; } + private _cachedVisibleSize: number | undefined; + get cachedVisibleSize(): number | undefined { return this._cachedVisibleSize; } + private _orthogonalSize: number; get orthogonalSize(): number { return this._orthogonalSize; } @@ -410,11 +475,12 @@ class LeafNode implements ISplitView, IDisposable { constructor( readonly view: IView, readonly orientation: Orientation, - orthogonalSize: number = 0 + readonly layoutController: ILayoutController, + orthogonalSize: number ) { this._orthogonalSize = orthogonalSize; - this._onDidViewChange = Event.map(this.view.onDidChange, this.orientation === Orientation.HORIZONTAL ? e => e && e.width : e => e && e.height); + this._onDidViewChange = Event.map(this.view.onDidChange, e => e && (this.orientation === Orientation.VERTICAL ? e.width : e.height)); this.onDidChange = Event.any(this._onDidViewChange, this._onDidSetLinkedNode.event, this._onDidLinkedWidthNodeChange.event, this._onDidLinkedHeightNodeChange.event); } @@ -458,8 +524,8 @@ class LeafNode implements ISplitView, IDisposable { return this.view.priority; } - get snapSize(): number | undefined { - return this.view.snapSize; + get snap(): boolean | undefined { + return this.view.snap; } get minimumOrthogonalSize(): number { @@ -480,12 +546,30 @@ class LeafNode implements ISplitView, IDisposable { layout(size: number): void { this._size = size; - return this.view.layout(this.width, this.height); + + if (this.layoutController.isLayoutEnabled) { + this.view.layout(this.width, this.height, orthogonal(this.orientation)); + } + } + + setVisible(visible: boolean): void { + if (visible) { + this._cachedVisibleSize = undefined; + } else { + this._cachedVisibleSize = this._size; + } + + if (this.view.setVisible) { + this.view.setVisible(visible); + } } orthogonalLayout(size: number): void { this._orthogonalSize = size; - return this.view.layout(this.width, this.height); + + if (this.layoutController.isLayoutEnabled) { + this.view.layout(this.width, this.height, orthogonal(this.orientation)); + } } dispose(): void { } @@ -516,7 +600,7 @@ function flipNode(node: T, size: number, orthogonalSize: number) return result as T; } else { - return new LeafNode((node as LeafNode).view, orthogonal(node.orientation), orthogonalSize) as T; + return new LeafNode((node as LeafNode).view, orthogonal(node.orientation), (node as LeafNode).layoutController, orthogonalSize) as T; } } @@ -526,7 +610,7 @@ export class GridView implements IDisposable { private styles: IGridViewStyles; private proportionalLayout: boolean; - private _root: BranchNode; + private _root!: BranchNode; private onDidSashResetRelay = new Relay(); readonly onDidSashReset: Event = this.onDidSashResetRelay.event; @@ -573,14 +657,17 @@ export class GridView implements IDisposable { get maximumWidth(): number { return this.root.maximumHeight; } get maximumHeight(): number { return this.root.maximumHeight; } - private _onDidChange = new Relay<{ width: number; height: number; } | undefined>(); + private _onDidChange = new Relay(); readonly onDidChange = this._onDidChange.event; + private layoutController: LayoutController; + constructor(options: IGridViewOptions = {}) { this.element = $('.monaco-grid-view'); this.styles = options.styles || defaultStyles; this.proportionalLayout = typeof options.proportionalLayout !== 'undefined' ? !!options.proportionalLayout : true; this.root = new BranchNode(Orientation.VERTICAL, this.styles, this.proportionalLayout); + this.layoutController = options.layoutController || new LayoutController(true); } style(styles: IGridViewStyles): void { @@ -602,26 +689,34 @@ export class GridView implements IDisposable { const [pathToParent, parent] = this.getNode(rest); if (parent instanceof BranchNode) { - const node = new LeafNode(view, orthogonal(parent.orientation), parent.orthogonalSize); + const node = new LeafNode(view, orthogonal(parent.orientation), this.layoutController, parent.orthogonalSize); parent.addChild(node, size, index); } else { const [, grandParent] = tail(pathToParent); const [, parentIndex] = tail(rest); + + let newSiblingSize: number | Sizing = 0; + + const newSiblingCachedVisibleSize = grandParent.getChildCachedVisibleSize(parentIndex); + if (typeof newSiblingCachedVisibleSize === 'number') { + newSiblingSize = Sizing.Invisible(newSiblingCachedVisibleSize); + } + grandParent.removeChild(parentIndex); const newParent = new BranchNode(parent.orientation, this.styles, this.proportionalLayout, parent.size, parent.orthogonalSize); grandParent.addChild(newParent, parent.size, parentIndex); newParent.orthogonalLayout(parent.orthogonalSize); - const newSibling = new LeafNode(parent.view, grandParent.orientation, parent.size); - newParent.addChild(newSibling, 0, 0); + const newSibling = new LeafNode(parent.view, grandParent.orientation, this.layoutController, parent.size); + newParent.addChild(newSibling, newSiblingSize, 0); if (typeof size !== 'number' && size.type === 'split') { size = Sizing.Split(0); } - const node = new LeafNode(view, grandParent.orientation, parent.size); + const node = new LeafNode(view, grandParent.orientation, this.layoutController, parent.size); newParent.addChild(node, size, index); } } @@ -683,7 +778,7 @@ export class GridView implements IDisposable { grandParent.addChild(child, child.size, parentIndex + i); } } else { - const newSibling = new LeafNode(sibling.view, orthogonal(sibling.orientation), sibling.size); + const newSibling = new LeafNode(sibling.view, orthogonal(sibling.orientation), this.layoutController, sibling.size); grandParent.addChild(newSibling, sibling.orthogonalSize, parentIndex); } @@ -747,18 +842,33 @@ export class GridView implements IDisposable { } } - resizeView(location: number[], size: number): void { + resizeView(location: number[], { width, height }: Partial): void { const [rest, index] = tail(location); - const [, parent] = this.getNode(rest); + const [pathToParent, parent] = this.getNode(rest); if (!(parent instanceof BranchNode)) { throw new Error('Invalid location'); } - parent.resizeChild(index, size); + if (!width && !height) { + return; + } + + const [parentSize, grandParentSize] = parent.orientation === Orientation.HORIZONTAL ? [width, height] : [height, width]; + + if (typeof grandParentSize === 'number' && pathToParent.length > 0) { + const [, grandParent] = tail(pathToParent); + const [, parentIndex] = tail(rest); + + grandParent.resizeChild(parentIndex, grandParentSize); + } + + if (typeof parentSize === 'number') { + parent.resizeChild(index, parentSize); + } } - getViewSize(location: number[]): { width: number; height: number; } { + getViewSize(location: number[]): IViewSize { const [, node] = this.getNode(location); return { width: node.width, height: node.height }; } @@ -790,13 +900,38 @@ export class GridView implements IDisposable { node.distributeViewSizes(); } - getViews(): GridBranchNode { - return this._getViews(this.root, this.orientation, { top: 0, left: 0, width: this.width, height: this.height }) as GridBranchNode; + isViewVisible(location: number[]): boolean { + const [rest, index] = tail(location); + const [, parent] = this.getNode(rest); + + if (!(parent instanceof BranchNode)) { + throw new Error('Invalid from location'); + } + + return parent.isChildVisible(index); + } + + setViewVisible(location: number[], visible: boolean): void { + const [rest, index] = tail(location); + const [, parent] = this.getNode(rest); + + if (!(parent instanceof BranchNode)) { + throw new Error('Invalid from location'); + } + + parent.setChildVisible(index, visible); + } + + getView(): GridBranchNode; + getView(location?: number[]): GridNode; + getView(location?: number[]): GridNode { + const node = location ? this.getNode(location)[1] : this._root; + return this._getViews(node, this.orientation, { top: 0, left: 0, width: this.width, height: this.height }); } private _getViews(node: Node, orientation: Orientation, box: Box): GridNode { if (node instanceof LeafNode) { - return { view: node.view, box }; + return { view: node.view, box, cachedVisibleSize: node.cachedVisibleSize }; } const children: GridNode[] = []; diff --git a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts index f98b11e6347..63c805b4237 100644 --- a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts +++ b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IDisposable } from 'vs/base/common/lifecycle'; -import * as dom from 'vs/base/browser/dom'; import * as objects from 'vs/base/common/objects'; import { renderOcticons } from 'vs/base/browser/ui/octiconLabel/octiconLabel'; import { escape } from 'vs/base/common/strings'; @@ -14,7 +12,7 @@ export interface IHighlight { end: number; } -export class HighlightedLabel implements IDisposable { +export class HighlightedLabel { private domNode: HTMLElement; private text: string; @@ -33,7 +31,7 @@ export class HighlightedLabel implements IDisposable { return this.domNode; } - set(text: string, highlights: IHighlight[] = [], title: string = '', escapeNewLines?: boolean) { + set(text: string | undefined, highlights: IHighlight[] = [], title: string = '', escapeNewLines?: boolean) { if (!text) { text = ''; } @@ -55,10 +53,9 @@ export class HighlightedLabel implements IDisposable { this.render(); } - private render() { - dom.clearNode(this.domNode); + private render(): void { - let htmlContent: string[] = []; + let htmlContent = ''; let pos = 0; for (const highlight of this.highlights) { @@ -66,42 +63,37 @@ export class HighlightedLabel implements IDisposable { continue; } if (pos < highlight.start) { - htmlContent.push(''); + htmlContent += ''; const substring = this.text.substring(pos, highlight.start); - htmlContent.push(this.supportOcticons ? renderOcticons(substring) : escape(substring)); - htmlContent.push(''); + htmlContent += this.supportOcticons ? renderOcticons(substring) : escape(substring); + htmlContent += ''; pos = highlight.end; } - htmlContent.push(''); + htmlContent += ''; const substring = this.text.substring(highlight.start, highlight.end); - htmlContent.push(this.supportOcticons ? renderOcticons(substring) : escape(substring)); - htmlContent.push(''); + htmlContent += this.supportOcticons ? renderOcticons(substring) : escape(substring); + htmlContent += ''; pos = highlight.end; } if (pos < this.text.length) { - htmlContent.push(''); + htmlContent += ''; const substring = this.text.substring(pos); - htmlContent.push(this.supportOcticons ? renderOcticons(substring) : escape(substring)); - htmlContent.push(''); + htmlContent += this.supportOcticons ? renderOcticons(substring) : escape(substring); + htmlContent += ''; } - this.domNode.innerHTML = htmlContent.join(''); + this.domNode.innerHTML = htmlContent; this.domNode.title = this.title; this.didEverRender = true; } - dispose() { - this.text = null!; // StrictNullOverride: nulling out ok in dispose - this.highlights = null!; // StrictNullOverride: nulling out ok in dispose - } - static escapeNewLines(text: string, highlights: IHighlight[]): string { let total = 0; let extra = 0; - return text.replace(/\r\n|\r|\n/, (match, offset) => { + return text.replace(/\r\n|\r|\n/g, (match, offset) => { extra = match === '\r\n' ? -1 : 0; offset += total; diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index be99067ee1d..a61b1bba525 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -100,13 +100,13 @@ export class IconLabel extends Disposable { this.labelDescriptionContainer = this._register(new FastLabelNode(dom.append(this.domNode.element, dom.$('.monaco-icon-label-description-container')))); if (options && options.supportHighlights) { - this.labelNode = this._register(new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name')), !options.donotSupportOcticons)); + this.labelNode = new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name')), !options.donotSupportOcticons); } else { this.labelNode = this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name')))); } if (options && options.supportDescriptionHighlights) { - this.descriptionNodeFactory = () => this._register(new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description')), !options.donotSupportOcticons)); + this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description')), !options.donotSupportOcticons); } else { this.descriptionNodeFactory = () => this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description')))); } @@ -157,4 +157,3 @@ export class IconLabel extends Disposable { } } } - diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts index 201cda1388d..d92ae6e2dae 100644 --- a/src/vs/base/browser/ui/inputbox/inputBox.ts +++ b/src/vs/base/browser/ui/inputbox/inputBox.ts @@ -28,22 +28,22 @@ export interface IInputOptions extends IInputBoxStyles { readonly type?: string; readonly validationOptions?: IInputValidationOptions; readonly flexibleHeight?: boolean; - readonly actions?: IAction[]; + readonly actions?: ReadonlyArray; } export interface IInputBoxStyles { - readonly inputBackground?: Color | null; - readonly inputForeground?: Color | null; - readonly inputBorder?: Color | null; - readonly inputValidationInfoBorder?: Color | null; - readonly inputValidationInfoBackground?: Color | null; - readonly inputValidationInfoForeground?: Color | null; - readonly inputValidationWarningBorder?: Color | null; - readonly inputValidationWarningBackground?: Color | null; - readonly inputValidationWarningForeground?: Color | null; - readonly inputValidationErrorBorder?: Color | null; - readonly inputValidationErrorBackground?: Color | null; - readonly inputValidationErrorForeground?: Color | null; + readonly inputBackground?: Color; + readonly inputForeground?: Color; + readonly inputBorder?: Color; + readonly inputValidationInfoBorder?: Color; + readonly inputValidationInfoBackground?: Color; + readonly inputValidationInfoForeground?: Color; + readonly inputValidationWarningBorder?: Color; + readonly inputValidationWarningBackground?: Color; + readonly inputValidationWarningForeground?: Color; + readonly inputValidationErrorBorder?: Color; + readonly inputValidationErrorBackground?: Color; + readonly inputValidationErrorForeground?: Color; } export interface IInputValidator { @@ -86,29 +86,29 @@ export class InputBox extends Widget { private contextViewProvider?: IContextViewProvider; element: HTMLElement; private input: HTMLInputElement; - private mirror: HTMLElement; + private mirror: HTMLElement | undefined; private actionbar?: ActionBar; private options: IInputOptions; private message: IMessage | null; private placeholder: string; private ariaLabel: string; private validation?: IInputValidator; - private state: string | null = 'idle'; + private state: 'idle' | 'open' | 'closed' = 'idle'; private cachedHeight: number | null; - private inputBackground?: Color | null; - private inputForeground?: Color | null; - private inputBorder?: Color | null; + private inputBackground?: Color; + private inputForeground?: Color; + private inputBorder?: Color; - private inputValidationInfoBorder?: Color | null; - private inputValidationInfoBackground?: Color | null; - private inputValidationInfoForeground?: Color | null; - private inputValidationWarningBorder?: Color | null; - private inputValidationWarningBackground?: Color | null; - private inputValidationWarningForeground?: Color | null; - private inputValidationErrorBorder?: Color | null; - private inputValidationErrorBackground?: Color | null; - private inputValidationErrorForeground?: Color | null; + private inputValidationInfoBorder?: Color; + private inputValidationInfoBackground?: Color; + private inputValidationInfoForeground?: Color; + private inputValidationWarningBorder?: Color; + private inputValidationWarningBackground?: Color; + private inputValidationWarningForeground?: Color; + private inputValidationErrorBorder?: Color; + private inputValidationErrorBackground?: Color; + private inputValidationErrorForeground?: Color; private _onDidChange = this._register(new Emitter()); public readonly onDidChange: Event = this._onDidChange.event; @@ -150,7 +150,7 @@ export class InputBox extends Widget { let tagName = this.options.flexibleHeight ? 'textarea' : 'input'; let wrapper = dom.append(this.element, $('.wrapper')); - this.input = dom.append(wrapper, $(tagName + '.input')); + this.input = dom.append(wrapper, $(tagName + '.input')); this.input.setAttribute('autocorrect', 'off'); this.input.setAttribute('autocapitalize', 'off'); this.input.setAttribute('spellcheck', 'false'); @@ -230,6 +230,10 @@ export class InputBox extends Widget { } } + public get mirrorElement(): HTMLElement | undefined { + return this.mirror; + } + public get inputElement(): HTMLInputElement { return this.input; } @@ -361,7 +365,7 @@ export class InputBox extends Widget { return !errorMsg; } - private stylesForType(type: MessageType | undefined): { border: Color | undefined | null; background: Color | undefined | null; foreground: Color | undefined | null } { + public stylesForType(type: MessageType | undefined): { border: Color | undefined; background: Color | undefined; foreground: Color | undefined } { switch (type) { case MessageType.INFO: return { border: this.inputValidationInfoBorder, background: this.inputValidationInfoBackground, foreground: this.inputValidationInfoForeground }; case MessageType.WARNING: return { border: this.inputValidationWarningBorder, background: this.inputValidationWarningBackground, foreground: this.inputValidationWarningForeground }; @@ -385,8 +389,6 @@ export class InputBox extends Widget { let div: HTMLElement; let layout = () => div.style.width = dom.getTotalWidth(this.element) + 'px'; - this.state = 'open'; - this.contextViewProvider.showContextView({ getAnchor: () => this.element, anchorAlignment: AnchorAlignment.RIGHT, @@ -417,18 +419,25 @@ export class InputBox extends Widget { return null; }, + onHide: () => { + this.state = 'closed'; + }, layout: layout }); + + this.state = 'open'; } private _hideMessage(): void { - if (!this.contextViewProvider || this.state !== 'open') { + if (!this.contextViewProvider) { return; } - this.state = 'idle'; + if (this.state === 'open') { + this.contextViewProvider.hideContextView(); + } - this.contextViewProvider.hideContextView(); + this.state = 'idle'; } private onValueChange(): void { @@ -518,7 +527,7 @@ export class InputBox extends Widget { this.contextViewProvider = undefined; this.message = null; this.validation = undefined; - this.state = null; + this.state = null!; // StrictNullOverride: nulling out ok in dispose this.actionbar = undefined; super.dispose(); diff --git a/src/vs/base/browser/ui/keybindingLabel/keybindingLabel.css b/src/vs/base/browser/ui/keybindingLabel/keybindingLabel.css index dd24df5df23..e33663d34b1 100644 --- a/src/vs/base/browser/ui/keybindingLabel/keybindingLabel.css +++ b/src/vs/base/browser/ui/keybindingLabel/keybindingLabel.css @@ -20,6 +20,15 @@ color: #555; font-size: 11px; padding: 3px 5px; + margin: 0 2px; +} + +.monaco-keybinding > .monaco-keybinding-key:first-child { + margin-left: 0; +} + +.monaco-keybinding > .monaco-keybinding-key:last-child { + margin-right: 0; } .hc-black .monaco-keybinding > .monaco-keybinding-key, @@ -36,5 +45,5 @@ } .monaco-keybinding > .monaco-keybinding-key-chord-separator { - width: 2px; + width: 6px; } \ No newline at end of file diff --git a/src/vs/base/browser/ui/keybindingLabel/keybindingLabel.ts b/src/vs/base/browser/ui/keybindingLabel/keybindingLabel.ts index ecc926434d6..e9fdc86be15 100644 --- a/src/vs/base/browser/ui/keybindingLabel/keybindingLabel.ts +++ b/src/vs/base/browser/ui/keybindingLabel/keybindingLabel.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./keybindingLabel'; -import { IDisposable } from 'vs/base/common/lifecycle'; import { equals } from 'vs/base/common/objects'; import { OperatingSystem } from 'vs/base/common/platform'; import { ResolvedKeybinding, ResolvedKeybindingPart } from 'vs/base/common/keyCodes'; import { UILabelProvider } from 'vs/base/common/keybindingLabels'; import * as dom from 'vs/base/browser/dom'; +import { localize } from 'vs/nls'; const $ = dom.$; @@ -26,14 +26,18 @@ export interface Matches { chordPart: PartMatches; } -export class KeybindingLabel implements IDisposable { +export interface KeybindingLabelOptions { + renderUnboundKeybindings: boolean; +} + +export class KeybindingLabel { private domNode: HTMLElement; - private keybinding: ResolvedKeybinding; - private matches: Matches; + private keybinding: ResolvedKeybinding | undefined; + private matches: Matches | undefined; private didEverRender: boolean; - constructor(container: HTMLElement, private os: OperatingSystem) { + constructor(container: HTMLElement, private os: OperatingSystem, private options?: KeybindingLabelOptions) { this.domNode = dom.append(container, $('.monaco-keybinding')); this.didEverRender = false; container.appendChild(this.domNode); @@ -43,7 +47,7 @@ export class KeybindingLabel implements IDisposable { return this.domNode; } - set(keybinding: ResolvedKeybinding, matches: Matches) { + set(keybinding: ResolvedKeybinding | undefined, matches?: Matches) { if (this.didEverRender && this.keybinding === keybinding && KeybindingLabel.areSame(this.matches, matches)) { return; } @@ -66,6 +70,8 @@ export class KeybindingLabel implements IDisposable { this.renderPart(this.domNode, chordPart, this.matches ? this.matches.chordPart : null); } this.domNode.title = this.keybinding.getAriaLabel() || ''; + } else if (this.options && this.options.renderUnboundKeybindings) { + this.renderUnbound(this.domNode); } this.didEverRender = true; @@ -98,10 +104,11 @@ export class KeybindingLabel implements IDisposable { } } - dispose() { + private renderUnbound(parent: HTMLElement): void { + dom.append(parent, $('span.monaco-keybinding-key', undefined, localize('unbound', "Unbound"))); } - private static areSame(a: Matches, b: Matches): boolean { + private static areSame(a: Matches | undefined, b: Matches | undefined): boolean { if (a === b || (!a && !b)) { return true; } diff --git a/src/vs/base/browser/ui/list/list.css b/src/vs/base/browser/ui/list/list.css index a651191df53..1c1fa4c8223 100644 --- a/src/vs/base/browser/ui/list/list.css +++ b/src/vs/base/browser/ui/list/list.css @@ -29,6 +29,11 @@ height: 100%; } +.monaco-list.horizontal-scrolling .monaco-list-rows { + width: auto; + min-width: 100%; +} + .monaco-list-row { position: absolute; -moz-box-sizing: border-box; @@ -52,4 +57,138 @@ /* Focus */ .monaco-list.element-focused, .monaco-list.selection-single, .monaco-list.selection-multiple { outline: 0 !important; +} + +/* Dnd */ +.monaco-drag-image { + display: inline-block; + padding: 1px 7px; + border-radius: 10px; + font-size: 12px; + position: absolute; +} + +/* Type filter */ + +.monaco-list-type-filter { + display: flex; + align-items: center; + position: absolute; + border-radius: 2px; + padding: 0px 3px; + max-width: calc(100% - 10px); + text-overflow: ellipsis; + overflow: hidden; + text-align: right; + box-sizing: border-box; + cursor: all-scroll; + font-size: 13px; + line-height: 18px; + height: 20px; + z-index: 1; + top: 4px; +} + +.monaco-list-type-filter.dragging { + transition: top 0.2s, left 0.2s; +} + +.monaco-list-type-filter.ne { + right: 4px; +} + +.monaco-list-type-filter.nw { + left: 4px; +} + +.monaco-list-type-filter > .controls { + display: flex; + align-items: center; + box-sizing: border-box; + transition: width 0.2s; + width: 0; +} + +.monaco-list-type-filter.dragging > .controls, +.monaco-list-type-filter:hover > .controls { + width: 36px; +} + +.monaco-list-type-filter > .controls > * { + box-sizing: border-box; + width: 16px; + height: 16px; + margin: 0 0 0 2px; + flex-shrink: 0; +} + +.monaco-list-type-filter > .controls > .filter { + -webkit-appearance: none; + width: 16px; + height: 16px; + background: url("media/no-filter-light.svg"); + background-position: 50% 50%; + cursor: pointer; +} + +.monaco-list-type-filter > .controls > .filter:checked { + background-image: url("media/filter-light.svg"); +} + +.vs-dark .monaco-list-type-filter > .controls > .filter { + background-image: url("media/no-filter-dark.svg"); +} + +.vs-dark .monaco-list-type-filter > .controls > .filter:checked { + background-image: url("media/filter-dark.svg"); +} + +.hc-black .monaco-list-type-filter > .controls > .filter { + background-image: url("media/no-filter-hc.svg"); +} + +.hc-black .monaco-list-type-filter > .controls > .filter:checked { + background-image: url("media/filter-hc.svg"); +} + +.monaco-list-type-filter > .controls > .clear { + border: none; + background: url("media/close-light.svg"); + cursor: pointer; +} + +.vs-dark .monaco-list-type-filter > .controls > .clear { + background-image: url("media/close-dark.svg"); +} + +.hc-black .monaco-list-type-filter > .controls > .clear { + background-image: url("media/close-hc.svg"); +} + +.monaco-list-type-filter-message { + position: absolute; + box-sizing: border-box; + width: 100%; + height: 100%; + top: 0; + left: 0; + padding: 40px 1em 1em 1em; + text-align: center; + white-space: normal; + opacity: 0.7; + pointer-events: none; +} + +.monaco-list-type-filter-message:empty { + display: none; +} + +/* Electron */ + +.monaco-list-type-filter { + cursor: grab; +} + +.monaco-list-type-filter.dragging { + cursor: grabbing; } \ No newline at end of file diff --git a/src/vs/base/browser/ui/list/list.ts b/src/vs/base/browser/ui/list/list.ts index 1db53632a68..2536dd0f270 100644 --- a/src/vs/base/browser/ui/list/list.ts +++ b/src/vs/base/browser/ui/list/list.ts @@ -5,20 +5,20 @@ import { GestureEvent } from 'vs/base/browser/touch'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { Event } from 'vs/base/common/event'; -import { IDisposable } from 'vs/base/common/lifecycle'; +import { IDragAndDropData } from 'vs/base/browser/dnd'; export interface IListVirtualDelegate { getHeight(element: T): number; getTemplateId(element: T): string; hasDynamicHeight?(element: T): boolean; + setDynamicHeight?(element: T, height: number): void; } export interface IListRenderer { templateId: string; renderTemplate(container: HTMLElement): TTemplateData; - renderElement(element: T, index: number, templateData: TTemplateData): void; - disposeElement?(element: T, index: number, templateData: TTemplateData): void; + renderElement(element: T, index: number, templateData: TTemplateData, height: number | undefined): void; + disposeElement?(element: T, index: number, templateData: TTemplateData, height: number | undefined): void; disposeTemplate(templateData: TTemplateData): void; } @@ -46,68 +46,62 @@ export interface IListGestureEvent { index: number | undefined; } +export interface IListDragEvent { + browserEvent: DragEvent; + element: T | undefined; + index: number | undefined; +} + export interface IListContextMenuEvent { browserEvent: UIEvent; element: T | undefined; index: number | undefined; - anchor: HTMLElement | { x: number; y: number; } | undefined; + anchor: HTMLElement | { x: number; y: number; }; } export interface IIdentityProvider { getId(element: T): { toString(): string; }; } +export enum ListAriaRootRole { + /** default tree structure role */ + TREE = 'tree', + + /** role='tree' can interfere with screenreaders reading nested elements inside the tree row. Use FORM in that case. */ + FORM = 'form' +} + export interface IKeyboardNavigationLabelProvider { - getKeyboardNavigationLabel(element: T): { toString(): string; }; + + /** + * Return a keyboard navigation label which will be used by the + * list for filtering/navigating. Return `undefined` to make an + * element always match. + */ + getKeyboardNavigationLabel(element: T): { toString(): string | undefined; } | undefined; mightProducePrintableCharacter?(event: IKeyboardEvent): boolean; } -/** - * Use this renderer when you want to re-render elements on account of - * an event firing. - */ -export abstract class AbstractListRenderer implements IListRenderer { +export const enum ListDragOverEffect { + Copy, + Move +} - private renderedElements = new Map(); - private listener: IDisposable; +export interface IListDragOverReaction { + accept: boolean; + effect?: ListDragOverEffect; + feedback?: number[]; // use -1 for entire list +} - constructor(onDidChange: Event) { - this.listener = onDidChange(this.onDidChange, this); - } +export const ListDragOverReactions = { + reject(): IListDragOverReaction { return { accept: false }; }, + accept(): IListDragOverReaction { return { accept: true }; }, +}; - renderElement(element: T, index: number, templateData: TTemplateData): void { - this.renderedElements.set(element, templateData); - } - - disposeElement(element: T, index: number, templateData: TTemplateData): void { - this.renderedElements.delete(element); - } - - private onDidChange(e: T | T[] | undefined) { - if (typeof e === 'undefined') { - this.renderedElements.forEach((templateData, element) => this.renderElement(element, -1 /* TODO@joao */, templateData)); - } else if (Array.isArray(e)) { - for (const element of e) { - this.rerender(element); - } - } else { - this.rerender(e); - } - } - - private rerender(element: T): void { - const templateData = this.renderedElements.get(element); - - if (templateData) { - this.renderElement(element, -1 /* TODO@Joao */, templateData); - } - } - - dispose(): void { - this.listener.dispose(); - } - - abstract readonly templateId: string; - abstract renderTemplate(container: HTMLElement): TTemplateData; - abstract disposeTemplate(templateData: TTemplateData): void; -} \ No newline at end of file +export interface IListDragAndDrop { + getDragURI(element: T): string | null; + getDragLabel?(elements: T[]): string | undefined; + onDragStart?(data: IDragAndDropData, originalEvent: DragEvent): void; + onDragOver(data: IDragAndDropData, targetElement: T | undefined, targetIndex: number | undefined, originalEvent: DragEvent): boolean | IListDragOverReaction; + drop(data: IDragAndDropData, targetElement: T | undefined, targetIndex: number | undefined, originalEvent: DragEvent): void; +} diff --git a/src/vs/base/browser/ui/list/listPaging.ts b/src/vs/base/browser/ui/list/listPaging.ts index 51129e1bd97..788c0045f2d 100644 --- a/src/vs/base/browser/ui/list/listPaging.ts +++ b/src/vs/base/browser/ui/list/listPaging.ts @@ -35,7 +35,7 @@ class PagedRenderer implements IListRenderer { } } }; } - renderElement(index: number, _: number, data: ITemplateData): void { + renderElement(index: number, _: number, data: ITemplateData, height: number | undefined): void { if (data.disposable) { data.disposable.dispose(); } @@ -47,7 +47,7 @@ class PagedRenderer implements IListRenderer implements IListRenderer cts.cancel() }; this.renderer.renderPlaceholder(index, data.data); - promise.then(entry => this.renderer.renderElement(entry, index, data.data!)); + promise.then(entry => this.renderer.renderElement(entry, index, data.data!, height)); } disposeTemplate(data: ITemplateData): void { @@ -73,7 +73,7 @@ class PagedRenderer implements IListRenderer implements IDisposable { private list: List; - private _model: IPagedModel; + private _model!: IPagedModel; constructor( container: HTMLElement, @@ -190,8 +190,12 @@ export class PagedList implements IDisposable { return this.list.getSelection(); } - layout(height?: number): void { - this.list.layout(height); + layout(height?: number, width?: number): void { + this.list.layout(height, width); + } + + toggleKeyboardNavigation(): void { + this.list.toggleKeyboardNavigation(); } reveal(index: number, relativeTop?: number): void { diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index b623ceacbe3..c35ddf1e1dd 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { getOrDefault } from 'vs/base/common/objects'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { Gesture, EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch'; import * as DOM from 'vs/base/browser/dom'; import { Event, Emitter } from 'vs/base/common/event'; @@ -12,26 +12,16 @@ import { domEvent } from 'vs/base/browser/event'; import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { ScrollEvent, ScrollbarVisibility, INewScrollDimensions } from 'vs/base/common/scrollable'; import { RangeMap, shift } from './rangeMap'; -import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListTouchEvent, IListGestureEvent } from './list'; +import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListTouchEvent, IListGestureEvent, IListDragEvent, IListDragAndDrop, ListDragOverEffect } from './list'; import { RowCache, IRow } from './rowCache'; import { isWindows } from 'vs/base/common/platform'; import * as browser from 'vs/base/browser/browser'; import { ISpliceable } from 'vs/base/common/sequence'; import { memoize } from 'vs/base/common/decorators'; -import { DragMouseEvent } from 'vs/base/browser/mouseEvent'; import { Range, IRange } from 'vs/base/common/range'; - -function canUseTranslate3d(): boolean { - if (browser.isFirefox) { - return false; - } - - if (browser.getZoomLevel() !== 0) { - return false; - } - - return true; -} +import { equals, distinct } from 'vs/base/common/arrays'; +import { DataTransfers, StaticDND, IDragAndDropData } from 'vs/base/browser/dnd'; +import { disposableTimeout, Delayer } from 'vs/base/common/async'; interface IItem { readonly id: string; @@ -39,27 +29,130 @@ interface IItem { readonly templateId: string; row: IRow | null; size: number; + width: number | undefined; hasDynamicHeight: boolean; - renderWidth: number | undefined; + lastDynamicHeightWidth: number | undefined; + uri: string | undefined; + dropTarget: boolean; + dragStartDisposable: IDisposable; } -export interface IListViewOptions { +export interface IListViewDragAndDrop extends IListDragAndDrop { + getDragElements(element: T): T[]; +} + +export interface IAriaProvider { + getSetSize(element: T, index: number, listLength: number): number; + getPosInSet(element: T, index: number): number; + getRole?(element: T): string; + isChecked?(element: T): boolean; +} + +export interface IListViewOptions { + readonly dnd?: IListViewDragAndDrop; readonly useShadows?: boolean; readonly verticalScrollMode?: ScrollbarVisibility; readonly setRowLineHeight?: boolean; readonly supportDynamicHeights?: boolean; readonly mouseSupport?: boolean; + readonly horizontalScrolling?: boolean; + readonly ariaProvider?: IAriaProvider; } const DefaultOptions = { useShadows: true, verticalScrollMode: ScrollbarVisibility.Auto, setRowLineHeight: true, - supportDynamicHeights: false + supportDynamicHeights: false, + dnd: { + getDragElements(e: T) { return [e]; }, + getDragURI() { return null; }, + onDragStart(): void { }, + onDragOver() { return false; }, + drop() { } + }, + horizontalScrolling: false }; +export class ElementsDragAndDropData implements IDragAndDropData { + + readonly elements: T[]; + + constructor(elements: T[]) { + this.elements = elements; + } + + update(): void { } + + getData(): any { + return this.elements; + } +} + +export class ExternalElementsDragAndDropData implements IDragAndDropData { + + readonly elements: T[]; + + constructor(elements: T[]) { + this.elements = elements; + } + + update(): void { } + + getData(): any { + return this.elements; + } +} + +export class DesktopDragAndDropData implements IDragAndDropData { + + readonly types: any[]; + readonly files: any[]; + + constructor() { + this.types = []; + this.files = []; + } + + update(dataTransfer: DataTransfer): void { + if (dataTransfer.types) { + this.types.splice(0, this.types.length, ...dataTransfer.types); + } + + if (dataTransfer.files) { + this.files.splice(0, this.files.length); + + for (let i = 0; i < dataTransfer.files.length; i++) { + const file = dataTransfer.files.item(i); + + if (file && (file.size || file.type)) { + this.files.push(file); + } + } + } + } + + getData(): any { + return { + types: this.types, + files: this.files + }; + } +} + +function equalsDragFeedback(f1: number[] | undefined, f2: number[] | undefined): boolean { + if (Array.isArray(f1) && Array.isArray(f2)) { + return equals(f1, f2!); + } + + return f1 === f2; +} + export class ListView implements ISpliceable, IDisposable { + private static InstanceCount = 0; + readonly domId = `list_id_${++ListView.InstanceCount}`; + readonly domNode: HTMLElement; private items: IItem[]; @@ -70,29 +163,47 @@ export class ListView implements ISpliceable, IDisposable { private lastRenderTop: number; private lastRenderHeight: number; private renderWidth = 0; - private gesture: Gesture; private rowsContainer: HTMLElement; private scrollableElement: ScrollableElement; - private _scrollHeight: number; + private _scrollHeight: number = 0; private scrollableElementUpdateDisposable: IDisposable | null = null; + private scrollableElementWidthDelayer = new Delayer(50); private splicing = false; - private dragAndDropScrollInterval: number; - private dragAndDropScrollTimeout: number; - private dragAndDropMouseY: number; + private dragOverAnimationDisposable: IDisposable | undefined; + private dragOverAnimationStopDisposable: IDisposable = Disposable.None; + private dragOverMouseY: number = 0; private setRowLineHeight: boolean; private supportDynamicHeights: boolean; + private horizontalScrolling: boolean; + private ariaProvider: IAriaProvider; + private scrollWidth: number | undefined; + private canUseTranslate3d: boolean | undefined = undefined; + + private dnd: IListViewDragAndDrop; + private canDrop: boolean = false; + private currentDragData: IDragAndDropData | undefined; + private currentDragFeedback: number[] | undefined; + private currentDragFeedbackDisposable: IDisposable = Disposable.None; + private onDragLeaveTimeout: IDisposable = Disposable.None; + private disposables: IDisposable[]; private _onDidChangeContentHeight = new Emitter(); readonly onDidChangeContentHeight: Event = Event.latch(this._onDidChangeContentHeight.event); get contentHeight(): number { return this.rangeMap.size; } + get onDidScroll(): Event { return this.scrollableElement.onScroll; } + constructor( container: HTMLElement, private virtualDelegate: IListVirtualDelegate, renderers: IListRenderer[], - options: IListViewOptions = DefaultOptions + options: IListViewOptions = DefaultOptions as IListViewOptions ) { + if (options.horizontalScrolling && options.supportDynamicHeights) { + throw new Error('Horizontal scrolling and dynamic heights not supported simultaneously'); + } + this.items = []; this.itemId = 0; this.rangeMap = new RangeMap(); @@ -108,15 +219,24 @@ export class ListView implements ISpliceable, IDisposable { this.domNode = document.createElement('div'); this.domNode.className = 'monaco-list'; + + DOM.addClass(this.domNode, this.domId); + this.domNode.tabIndex = 0; + DOM.toggleClass(this.domNode, 'mouse-support', typeof options.mouseSupport === 'boolean' ? options.mouseSupport : true); + this.horizontalScrolling = getOrDefault(options, o => o.horizontalScrolling, DefaultOptions.horizontalScrolling); + DOM.toggleClass(this.domNode, 'horizontal-scrolling', this.horizontalScrolling); + + this.ariaProvider = options.ariaProvider || { getSetSize: (e, i, length) => length, getPosInSet: (_, index) => index + 1 }; + this.rowsContainer = document.createElement('div'); this.rowsContainer.className = 'monaco-list-rows'; Gesture.addTarget(this.rowsContainer); this.scrollableElement = new ScrollableElement(this.rowsContainer, { alwaysConsumeMouseWheel: true, - horizontal: ScrollbarVisibility.Hidden, + horizontal: this.horizontalScrolling ? ScrollbarVisibility.Auto : ScrollbarVisibility.Hidden, vertical: getOrDefault(options, o => o.verticalScrollMode, DefaultOptions.verticalScrollMode), useShadows: getOrDefault(options, o => o.useShadows, DefaultOptions.useShadows) }); @@ -124,7 +244,7 @@ export class ListView implements ISpliceable, IDisposable { this.domNode.appendChild(this.scrollableElement.getDomNode()); container.appendChild(this.domNode); - this.disposables = [this.rangeMap, this.gesture, this.scrollableElement, this.cache]; + this.disposables = [this.rangeMap, this.scrollableElement, this.cache]; this.scrollableElement.onScroll(this.onScroll, this, this.disposables); domEvent(this.rowsContainer, TouchEventType.Change)(this.onTouchChange, this, this.disposables); @@ -134,11 +254,14 @@ export class ListView implements ISpliceable, IDisposable { domEvent(this.scrollableElement.getDomNode(), 'scroll') (e => (e.target as HTMLElement).scrollTop = 0, null, this.disposables); - const onDragOver = Event.map(domEvent(this.rowsContainer, 'dragover'), e => new DragMouseEvent(e)); - onDragOver(this.onDragOver, this, this.disposables); + Event.map(domEvent(this.domNode, 'dragover'), e => this.toDragEvent(e))(this.onDragOver, this, this.disposables); + Event.map(domEvent(this.domNode, 'drop'), e => this.toDragEvent(e))(this.onDrop, this, this.disposables); + domEvent(this.domNode, 'dragleave')(this.onDragLeave, this, this.disposables); + domEvent(window, 'dragend')(this.onDragEnd, this, this.disposables); this.setRowLineHeight = getOrDefault(options, o => o.setRowLineHeight, DefaultOptions.setRowLineHeight); this.supportDynamicHeights = getOrDefault(options, o => o.supportDynamicHeights, DefaultOptions.supportDynamicHeights); + this.dnd = getOrDefault, IListViewDragAndDrop>(options, o => o.dnd, DefaultOptions.dnd); this.layout(); } @@ -176,9 +299,13 @@ export class ListView implements ISpliceable, IDisposable { element, templateId: this.virtualDelegate.getTemplateId(element), size: this.virtualDelegate.getHeight(element), + width: undefined, hasDynamicHeight: !!this.virtualDelegate.hasDynamicHeight && this.virtualDelegate.hasDynamicHeight(element), - renderWidth: undefined, - row: null + lastDynamicHeightWidth: undefined, + row: null, + uri: undefined, + dropTarget: false, + dragStartDisposable: Disposable.None })); let deleted: IItem[]; @@ -222,27 +349,83 @@ export class ListView implements ISpliceable, IDisposable { } } - this.updateScrollHeight(); + this.eventuallyUpdateScrollDimensions(); if (this.supportDynamicHeights) { - this.rerender(this.scrollTop, this.renderHeight); + this._rerender(this.scrollTop, this.renderHeight); } return deleted.map(i => i.element); } - private updateScrollHeight(): void { + private eventuallyUpdateScrollDimensions(): void { this._scrollHeight = this.contentHeight; this.rowsContainer.style.height = `${this._scrollHeight}px`; if (!this.scrollableElementUpdateDisposable) { this.scrollableElementUpdateDisposable = DOM.scheduleAtNextAnimationFrame(() => { - this.scrollableElement.setScrollDimensions({ scrollHeight: this._scrollHeight }); + this.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight }); + this.updateScrollWidth(); this.scrollableElementUpdateDisposable = null; }); } } + private eventuallyUpdateScrollWidth(): void { + if (!this.horizontalScrolling) { + return; + } + + this.scrollableElementWidthDelayer.trigger(() => this.updateScrollWidth()); + } + + private updateScrollWidth(): void { + if (!this.horizontalScrolling) { + return; + } + + if (this.items.length === 0) { + this.scrollableElement.setScrollDimensions({ scrollWidth: 0 }); + } + + let scrollWidth = 0; + + for (const item of this.items) { + if (typeof item.width !== 'undefined') { + scrollWidth = Math.max(scrollWidth, item.width); + } + } + + this.scrollWidth = scrollWidth; + this.scrollableElement.setScrollDimensions({ scrollWidth: scrollWidth + 10 }); + } + + updateWidth(index: number): void { + if (!this.horizontalScrolling || typeof this.scrollWidth === 'undefined') { + return; + } + + const item = this.items[index]; + this.measureItemWidth(item); + + if (typeof item.width !== 'undefined' && item.width > this.scrollWidth) { + this.scrollWidth = item.width; + this.scrollableElement.setScrollDimensions({ scrollWidth: this.scrollWidth + 10 }); + } + } + + rerender(): void { + if (!this.supportDynamicHeights) { + return; + } + + for (const item of this.items) { + item.lastDynamicHeightWidth = undefined; + } + + this._rerender(this.lastRenderTop, this.lastRenderHeight); + } + get length(): number { return this.items.length; } @@ -252,6 +435,25 @@ export class ListView implements ISpliceable, IDisposable { return scrollDimensions.height; } + get firstVisibleIndex(): number { + const range = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight); + const firstElTop = this.rangeMap.positionAt(range.start); + const nextElTop = this.rangeMap.positionAt(range.start + 1); + if (nextElTop !== -1) { + const firstElMidpoint = (nextElTop - firstElTop) / 2 + firstElTop; + if (firstElMidpoint < this.scrollTop) { + return range.start + 1; + } + } + + return range.start; + } + + get lastVisibleIndex(): number { + const range = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight); + return range.end - 1; + } + element(index: number): T { return this.items[index].element; } @@ -277,31 +479,37 @@ export class ListView implements ISpliceable, IDisposable { return this.rangeMap.indexAfter(position); } - layout(height?: number): void { + layout(height?: number, width?: number): void { let scrollDimensions: INewScrollDimensions = { - height: height || DOM.getContentHeight(this.domNode) + height: typeof height === 'number' ? height : DOM.getContentHeight(this.domNode) }; if (this.scrollableElementUpdateDisposable) { this.scrollableElementUpdateDisposable.dispose(); this.scrollableElementUpdateDisposable = null; - scrollDimensions.scrollHeight = this._scrollHeight; + scrollDimensions.scrollHeight = this.scrollHeight; } this.scrollableElement.setScrollDimensions(scrollDimensions); - } - layoutWidth(width: number): void { - this.renderWidth = width; + if (typeof width !== 'undefined') { + this.renderWidth = width; - if (this.supportDynamicHeights) { - this.rerender(this.scrollTop, this.renderHeight); + if (this.supportDynamicHeights) { + this._rerender(this.scrollTop, this.renderHeight); + } + + if (this.horizontalScrolling) { + this.scrollableElement.setScrollDimensions({ + width: typeof width === 'number' ? width : DOM.getContentWidth(this.domNode) + }); + } } } // Render - private render(renderTop: number, renderHeight: number): void { + private render(renderTop: number, renderHeight: number, renderLeft: number, scrollWidth: number): void { const previousRenderRange = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight); const renderRange = this.getRenderRange(renderTop, renderHeight); @@ -321,14 +529,33 @@ export class ListView implements ISpliceable, IDisposable { } } - if (canUseTranslate3d() && !isWindows /* Windows: translate3d breaks subpixel-antialias (ClearType) unless a background is defined */) { - const transform = `translate3d(0px, -${renderTop}px, 0px)`; + const canUseTranslate3d = !isWindows && !browser.isFirefox && browser.getZoomLevel() === 0; + + if (canUseTranslate3d) { + const transform = `translate3d(-${renderLeft}px, -${renderTop}px, 0px)`; this.rowsContainer.style.transform = transform; this.rowsContainer.style.webkitTransform = transform; + + if (canUseTranslate3d !== this.canUseTranslate3d) { + this.rowsContainer.style.left = '0'; + this.rowsContainer.style.top = '0'; + } } else { + this.rowsContainer.style.left = `-${renderLeft}px`; this.rowsContainer.style.top = `-${renderTop}px`; + + if (canUseTranslate3d !== this.canUseTranslate3d) { + this.rowsContainer.style.transform = ''; + this.rowsContainer.style.webkitTransform = ''; + } } + if (this.horizontalScrolling) { + this.rowsContainer.style.width = `${Math.max(scrollWidth, this.renderWidth)}px`; + } + + this.canUseTranslate3d = canUseTranslate3d; + this.lastRenderTop = renderTop; this.lastRenderHeight = renderHeight; } @@ -340,6 +567,12 @@ export class ListView implements ISpliceable, IDisposable { if (!item.row) { item.row = this.cache.alloc(item.templateId); + const role = this.ariaProvider.getRole ? this.ariaProvider.getRole(item.element) : 'treeitem'; + item.row!.domNode!.setAttribute('role', role); + const checked = this.ariaProvider.isChecked ? this.ariaProvider.isChecked(item.element) : undefined; + if (typeof checked !== 'undefined') { + item.row!.domNode!.setAttribute('aria-checked', String(checked)); + } } if (!item.row.domNode!.parentElement) { @@ -353,7 +586,48 @@ export class ListView implements ISpliceable, IDisposable { this.updateItemInDOM(item, index); const renderer = this.renderers.get(item.templateId); - renderer.renderElement(item.element, index, item.row.templateData); + + if (!renderer) { + throw new Error(`No renderer found for template id ${item.templateId}`); + } + + if (renderer) { + renderer.renderElement(item.element, index, item.row.templateData, item.size); + } + + const uri = this.dnd.getDragURI(item.element); + item.dragStartDisposable.dispose(); + item.row.domNode!.draggable = !!uri; + + if (uri) { + const onDragStart = domEvent(item.row.domNode!, 'dragstart'); + item.dragStartDisposable = onDragStart(event => this.onDragStart(item.element, uri, event)); + } + + if (this.horizontalScrolling) { + this.measureItemWidth(item); + this.eventuallyUpdateScrollWidth(); + } + } + + private measureItemWidth(item: IItem): void { + if (!item.row || !item.row.domNode) { + return; + } + + item.row.domNode.style.width = 'fit-content'; + item.width = DOM.getContentWidth(item.row.domNode); + const style = window.getComputedStyle(item.row.domNode); + + if (style.paddingLeft) { + item.width += parseFloat(style.paddingLeft); + } + + if (style.paddingRight) { + item.width += parseFloat(style.paddingRight); + } + + item.row.domNode.style.width = ''; } private updateItemInDOM(item: IItem, index: number): void { @@ -366,24 +640,28 @@ export class ListView implements ISpliceable, IDisposable { item.row!.domNode!.setAttribute('data-index', `${index}`); item.row!.domNode!.setAttribute('data-last-element', index === this.length - 1 ? 'true' : 'false'); - item.row!.domNode!.setAttribute('aria-setsize', `${this.length}`); - item.row!.domNode!.setAttribute('aria-posinset', `${index + 1}`); + item.row!.domNode!.setAttribute('aria-setsize', String(this.ariaProvider.getSetSize(item.element, index, this.length))); + item.row!.domNode!.setAttribute('aria-posinset', String(this.ariaProvider.getPosInSet(item.element, index))); + item.row!.domNode!.setAttribute('id', this.getElementDomId(index)); + + DOM.toggleClass(item.row!.domNode!, 'drop-target', item.dropTarget); } private removeItemFromDOM(index: number): void { const item = this.items[index]; + item.dragStartDisposable.dispose(); + const renderer = this.renderers.get(item.templateId); - - if (!item.row) { - return; - } - - if (renderer.disposeElement) { - renderer.disposeElement(item.element, index, item.row!.templateData); + if (renderer && renderer.disposeElement) { + renderer.disposeElement(item.element, index, item.row!.templateData, item.size); } this.cache.release(item.row!); item.row = null; + + if (this.horizontalScrolling) { + this.eventuallyUpdateScrollWidth(); + } } getScrollTop(): number { @@ -395,7 +673,7 @@ export class ListView implements ISpliceable, IDisposable { if (this.scrollableElementUpdateDisposable) { this.scrollableElementUpdateDisposable.dispose(); this.scrollableElementUpdateDisposable = null; - this.scrollableElement.setScrollDimensions({ scrollHeight: this._scrollHeight }); + this.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight }); } this.scrollableElement.setScrollPosition({ scrollTop }); @@ -410,7 +688,7 @@ export class ListView implements ISpliceable, IDisposable { } get scrollHeight(): number { - return this._scrollHeight; + return this._scrollHeight + (this.horizontalScrolling ? 10 : 0); } // Events @@ -448,12 +726,19 @@ export class ListView implements ISpliceable, IDisposable { return { browserEvent, index, element }; } + private toDragEvent(browserEvent: DragEvent): IListDragEvent { + const index = this.getItemIndexFromEventTarget(browserEvent.target || null); + const item = typeof index === 'undefined' ? undefined : this.items[index]; + const element = item && item.element; + return { browserEvent, index, element }; + } + private onScroll(e: ScrollEvent): void { try { - this.render(e.scrollTop, e.height); + this.render(e.scrollTop, e.height, e.scrollLeft, e.scrollWidth); if (this.supportDynamicHeights) { - this.rerender(e.scrollTop, e.height); + this._rerender(e.scrollTop, e.height); } } catch (err) { console.error('Got bad scroll event:', e); @@ -468,55 +753,220 @@ export class ListView implements ISpliceable, IDisposable { this.scrollTop -= event.translationY; } - private onDragOver(event: DragMouseEvent): void { - this.setupDragAndDropScrollInterval(); - this.dragAndDropMouseY = event.posy; - } + // DND - private setupDragAndDropScrollInterval(): void { - const viewTop = DOM.getTopLeftOffset(this.domNode).top; + private onDragStart(element: T, uri: string, event: DragEvent): void { + if (!event.dataTransfer) { + return; + } - if (!this.dragAndDropScrollInterval) { - this.dragAndDropScrollInterval = window.setInterval(() => { - if (this.dragAndDropMouseY === undefined) { - return; - } + const elements = this.dnd.getDragElements(element); - let diff = this.dragAndDropMouseY - viewTop; - let scrollDiff = 0; - let upperLimit = this.renderHeight - 35; + event.dataTransfer.effectAllowed = 'copyMove'; + event.dataTransfer.setData(DataTransfers.RESOURCES, JSON.stringify([uri])); - if (diff < 35) { - scrollDiff = Math.max(-14, 0.2 * (diff - 35)); - } else if (diff > upperLimit) { - scrollDiff = Math.min(14, 0.2 * (diff - upperLimit)); - } + if (event.dataTransfer.setDragImage) { + let label: string | undefined; - this.scrollTop += scrollDiff; - }, 10); + if (this.dnd.getDragLabel) { + label = this.dnd.getDragLabel(elements); + } - this.cancelDragAndDropScrollTimeout(); + if (typeof label === 'undefined') { + label = String(elements.length); + } - this.dragAndDropScrollTimeout = window.setTimeout(() => { - this.cancelDragAndDropScrollInterval(); - this.dragAndDropScrollTimeout = -1; - }, 1000); + const dragImage = DOM.$('.monaco-drag-image'); + dragImage.textContent = label; + document.body.appendChild(dragImage); + event.dataTransfer.setDragImage(dragImage, -10, -10); + setTimeout(() => document.body.removeChild(dragImage), 0); + } + + this.currentDragData = new ElementsDragAndDropData(elements); + StaticDND.CurrentDragAndDropData = new ExternalElementsDragAndDropData(elements); + + if (this.dnd.onDragStart) { + this.dnd.onDragStart(this.currentDragData, event); } } - private cancelDragAndDropScrollInterval(): void { - if (this.dragAndDropScrollInterval) { - window.clearInterval(this.dragAndDropScrollInterval); - this.dragAndDropScrollInterval = -1; + private onDragOver(event: IListDragEvent): boolean { + event.browserEvent.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome) + + this.onDragLeaveTimeout.dispose(); + + if (StaticDND.CurrentDragAndDropData && StaticDND.CurrentDragAndDropData.getData() === 'vscode-ui') { + return false; } - this.cancelDragAndDropScrollTimeout(); + this.setupDragAndDropScrollTopAnimation(event.browserEvent); + + if (!event.browserEvent.dataTransfer) { + return false; + } + + // Drag over from outside + if (!this.currentDragData) { + if (StaticDND.CurrentDragAndDropData) { + // Drag over from another list + this.currentDragData = StaticDND.CurrentDragAndDropData; + + } else { + // Drag over from the desktop + if (!event.browserEvent.dataTransfer.types) { + return false; + } + + this.currentDragData = new DesktopDragAndDropData(); + } + } + + const result = this.dnd.onDragOver(this.currentDragData, event.element, event.index, event.browserEvent); + this.canDrop = typeof result === 'boolean' ? result : result.accept; + + if (!this.canDrop) { + this.currentDragFeedback = undefined; + this.currentDragFeedbackDisposable.dispose(); + return false; + } + + event.browserEvent.dataTransfer.dropEffect = (typeof result !== 'boolean' && result.effect === ListDragOverEffect.Copy) ? 'copy' : 'move'; + + let feedback: number[]; + + if (typeof result !== 'boolean' && result.feedback) { + feedback = result.feedback; + } else { + if (typeof event.index === 'undefined') { + feedback = [-1]; + } else { + feedback = [event.index]; + } + } + + // sanitize feedback list + feedback = distinct(feedback).filter(i => i >= -1 && i < this.length).sort(); + feedback = feedback[0] === -1 ? [-1] : feedback; + + if (feedback.length === 0) { + throw new Error('Invalid empty feedback list'); + } + + if (equalsDragFeedback(this.currentDragFeedback, feedback)) { + return true; + } + + this.currentDragFeedback = feedback; + this.currentDragFeedbackDisposable.dispose(); + + if (feedback[0] === -1) { // entire list feedback + DOM.addClass(this.domNode, 'drop-target'); + this.currentDragFeedbackDisposable = toDisposable(() => DOM.removeClass(this.domNode, 'drop-target')); + } else { + for (const index of feedback) { + const item = this.items[index]!; + item.dropTarget = true; + + if (item.row && item.row.domNode) { + DOM.addClass(item.row.domNode, 'drop-target'); + } + } + + this.currentDragFeedbackDisposable = toDisposable(() => { + for (const index of feedback) { + const item = this.items[index]!; + item.dropTarget = false; + + if (item.row && item.row.domNode) { + DOM.removeClass(item.row.domNode, 'drop-target'); + } + } + }); + } + + return true; } - private cancelDragAndDropScrollTimeout(): void { - if (this.dragAndDropScrollTimeout) { - window.clearTimeout(this.dragAndDropScrollTimeout); - this.dragAndDropScrollTimeout = -1; + private onDragLeave(): void { + this.onDragLeaveTimeout.dispose(); + this.onDragLeaveTimeout = disposableTimeout(() => this.clearDragOverFeedback(), 100); + } + + private onDrop(event: IListDragEvent): void { + if (!this.canDrop) { + return; + } + + const dragData = this.currentDragData; + this.teardownDragAndDropScrollTopAnimation(); + this.clearDragOverFeedback(); + this.currentDragData = undefined; + StaticDND.CurrentDragAndDropData = undefined; + + if (!dragData || !event.browserEvent.dataTransfer) { + return; + } + + event.browserEvent.preventDefault(); + dragData.update(event.browserEvent.dataTransfer); + this.dnd.drop(dragData, event.element, event.index, event.browserEvent); + } + + private onDragEnd(): void { + this.canDrop = false; + this.teardownDragAndDropScrollTopAnimation(); + this.clearDragOverFeedback(); + this.currentDragData = undefined; + StaticDND.CurrentDragAndDropData = undefined; + } + + private clearDragOverFeedback(): void { + this.currentDragFeedback = undefined; + this.currentDragFeedbackDisposable.dispose(); + this.currentDragFeedbackDisposable = Disposable.None; + } + + // DND scroll top animation + + private setupDragAndDropScrollTopAnimation(event: DragEvent): void { + if (!this.dragOverAnimationDisposable) { + const viewTop = DOM.getTopLeftOffset(this.domNode).top; + this.dragOverAnimationDisposable = DOM.animate(this.animateDragAndDropScrollTop.bind(this, viewTop)); + } + + this.dragOverAnimationStopDisposable.dispose(); + this.dragOverAnimationStopDisposable = disposableTimeout(() => { + if (this.dragOverAnimationDisposable) { + this.dragOverAnimationDisposable.dispose(); + this.dragOverAnimationDisposable = undefined; + } + }, 1000); + + this.dragOverMouseY = event.pageY; + } + + private animateDragAndDropScrollTop(viewTop: number): void { + if (this.dragOverMouseY === undefined) { + return; + } + + const diff = this.dragOverMouseY - viewTop; + const upperLimit = this.renderHeight - 35; + + if (diff < 35) { + this.scrollTop += Math.max(-14, Math.floor(0.3 * (diff - 35))); + } else if (diff > upperLimit) { + this.scrollTop += Math.min(14, Math.floor(0.3 * (diff - upperLimit))); + } + } + + private teardownDragAndDropScrollTopAnimation(): void { + this.dragOverAnimationStopDisposable.dispose(); + + if (this.dragOverAnimationDisposable) { + this.dragOverAnimationDisposable.dispose(); + this.dragOverAnimationDisposable = undefined; } } @@ -553,17 +1003,20 @@ export class ListView implements ISpliceable, IDisposable { * Given a stable rendered state, checks every rendered element whether it needs * to be probed for dynamic height. Adjusts scroll height and top if necessary. */ - private rerender(renderTop: number, renderHeight: number): void { + private _rerender(renderTop: number, renderHeight: number): void { const previousRenderRange = this.getRenderRange(renderTop, renderHeight); // Let's remember the second element's position, this helps in scrolling up // and preserving a linear upwards scroll movement - let secondElementIndex: number | undefined; - let secondElementTopDelta: number | undefined; + let anchorElementIndex: number | undefined; + let anchorElementTopDelta: number | undefined; - if (previousRenderRange.end - previousRenderRange.start > 1) { - secondElementIndex = previousRenderRange.start + 1; - secondElementTopDelta = this.elementTop(secondElementIndex) - renderTop; + if (renderTop === this.elementTop(previousRenderRange.start)) { + anchorElementIndex = previousRenderRange.start; + anchorElementTopDelta = 0; + } else if (previousRenderRange.end - previousRenderRange.start > 1) { + anchorElementIndex = previousRenderRange.start + 1; + anchorElementTopDelta = this.elementTop(anchorElementIndex) - renderTop; } let heightDiff = 0; @@ -586,7 +1039,7 @@ export class ListView implements ISpliceable, IDisposable { if (!didChange) { if (heightDiff !== 0) { - this.updateScrollHeight(); + this.eventuallyUpdateScrollDimensions(); } const unrenderRanges = Range.relativeComplement(previousRenderRange, renderRange); @@ -599,14 +1052,25 @@ export class ListView implements ISpliceable, IDisposable { } } + const renderRanges = Range.relativeComplement(renderRange, previousRenderRange); + + for (const range of renderRanges) { + for (let i = range.start; i < range.end; i++) { + const afterIndex = i + 1; + const beforeRow = afterIndex < this.items.length ? this.items[afterIndex].row : null; + const beforeElement = beforeRow ? beforeRow.domNode : null; + this.insertItemInDOM(i, beforeElement); + } + } + for (let i = renderRange.start; i < renderRange.end; i++) { if (this.items[i].row) { this.updateItemInDOM(this.items[i], i); } } - if (typeof secondElementIndex === 'number') { - this.scrollTop = this.elementTop(secondElementIndex) - secondElementTopDelta!; + if (typeof anchorElementIndex === 'number') { + this.scrollTop = this.elementTop(anchorElementIndex) - anchorElementTopDelta!; } this._onDidChangeContentHeight.fire(this.contentHeight); @@ -618,19 +1082,32 @@ export class ListView implements ISpliceable, IDisposable { private probeDynamicHeight(index: number): number { const item = this.items[index]; - if (!item.hasDynamicHeight || item.renderWidth === this.renderWidth) { + if (!item.hasDynamicHeight || item.lastDynamicHeightWidth === this.renderWidth) { return 0; } const size = item.size; - const renderer = this.renderers.get(item.templateId); const row = this.cache.alloc(item.templateId); row.domNode!.style.height = ''; this.rowsContainer.appendChild(row.domNode!); - renderer.renderElement(item.element, index, row.templateData); + + const renderer = this.renderers.get(item.templateId); + if (renderer) { + renderer.renderElement(item.element, index, row.templateData, undefined); + + if (renderer.disposeElement) { + renderer.disposeElement(item.element, index, row.templateData, undefined); + } + } + item.size = row.domNode!.offsetHeight; - item.renderWidth = this.renderWidth; + + if (this.virtualDelegate.setDynamicHeight) { + this.virtualDelegate.setDynamicHeight(item.element, item.size); + } + + item.lastDynamicHeightWidth = this.renderWidth; this.rowsContainer.removeChild(row.domNode!); this.cache.release(row); @@ -657,6 +1134,10 @@ export class ListView implements ISpliceable, IDisposable { return nextToLastItem.row.domNode; } + getElementDomId(index: number): string { + return `${this.domId}_${index}`; + } + // Dispose dispose() { @@ -664,7 +1145,9 @@ export class ListView implements ISpliceable, IDisposable { for (const item of this.items) { if (item.row) { const renderer = this.renderers.get(item.row.templateId); - renderer.disposeTemplate(item.row.templateData); + if (renderer) { + renderer.disposeTemplate(item.row.templateData); + } } } diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index b7ccbc9f294..24fec080908 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -5,9 +5,9 @@ import 'vs/css!./list'; import { localize } from 'vs/nls'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle'; import { isNumber } from 'vs/base/common/types'; -import { range, firstIndex } from 'vs/base/common/arrays'; +import { range, firstIndex, binarySearch } from 'vs/base/common/arrays'; import { memoize } from 'vs/base/common/decorators'; import * as DOM from 'vs/base/browser/dom'; import * as platform from 'vs/base/common/platform'; @@ -16,15 +16,16 @@ 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 { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent, IListTouchEvent, IListGestureEvent, IIdentityProvider, IKeyboardNavigationLabelProvider } from './list'; -import { ListView, IListViewOptions } from './listView'; +import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent, IListTouchEvent, IListGestureEvent, IIdentityProvider, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, ListAriaRootRole } from './list'; +import { ListView, IListViewOptions, IListViewDragAndDrop, IAriaProvider } from './listView'; import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; -import { ScrollbarVisibility } from 'vs/base/common/scrollable'; +import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable'; import { ISpliceable } from 'vs/base/common/sequence'; import { CombinedSpliceable } from 'vs/base/browser/ui/list/splice'; import { clamp } from 'vs/base/common/numbers'; import { matchesPrefix } from 'vs/base/common/filters'; +import { IDragAndDropData } from 'vs/base/browser/dnd'; interface ITraitChangeEvent { indexes: number[]; @@ -106,13 +107,11 @@ class TraitRenderer implements IListRenderer class Trait implements ISpliceable, IDisposable { - /** - * Sorted indexes which have this trait. - */ - private indexes: number[]; + private indexes: number[] = []; + private sortedIndexes: number[] = []; private _onChange = new Emitter(); - get onChange(): Event { return this._onChange.event; } + readonly onChange: Event = this._onChange.event; get trait(): string { return this._trait; } @@ -121,21 +120,19 @@ class Trait implements ISpliceable, IDisposable { return new TraitRenderer(this); } - constructor(private _trait: string) { - this.indexes = []; - } + constructor(private _trait: string) { } splice(start: number, deleteCount: number, elements: boolean[]): void { const diff = elements.length - deleteCount; const end = start + deleteCount; const indexes = [ - ...this.indexes.filter(i => i < start), + ...this.sortedIndexes.filter(i => i < start), ...elements.map((hasTrait, i) => hasTrait ? i + start : -1).filter(i => i !== -1), - ...this.indexes.filter(i => i >= end).map(i => i + diff) + ...this.sortedIndexes.filter(i => i >= end).map(i => i + diff) ]; this.renderer.splice(start, deleteCount, elements.length); - this.set(indexes); + this._set(indexes, indexes); } renderIndex(index: number, container: HTMLElement): void { @@ -153,10 +150,17 @@ class Trait implements ISpliceable, IDisposable { * @return The old indexes which had this trait. */ set(indexes: number[], browserEvent?: UIEvent): number[] { - const result = this.indexes; - this.indexes = indexes; + return this._set(indexes, [...indexes].sort(numericSort), browserEvent); + } - const toRender = disjunction(result, indexes); + private _set(indexes: number[], sortedIndexes: number[], browserEvent?: UIEvent): number[] { + const result = this.indexes; + const sortedResult = this.sortedIndexes; + + this.indexes = indexes; + this.sortedIndexes = sortedIndexes; + + const toRender = disjunction(sortedResult, indexes); this.renderer.renderIndexes(toRender); this._onChange.fire({ indexes, browserEvent }); @@ -168,7 +172,7 @@ class Trait implements ISpliceable, IDisposable { } contains(index: number): boolean { - return this.indexes.some(i => i === index); + return binarySearch(this.sortedIndexes, index, numericSort) >= 0; } dispose() { @@ -178,16 +182,12 @@ class Trait implements ISpliceable, IDisposable { class FocusTrait extends Trait { - constructor( - private getDomId: (index: number) => string - ) { + constructor() { super('focused'); } renderIndex(index: number, container: HTMLElement): void { super.renderIndex(index, container); - container.setAttribute('role', 'treeitem'); - container.setAttribute('id', this.getDomId(index)); if (this.contains(index)) { container.setAttribute('aria-selected', 'true'); @@ -212,7 +212,7 @@ class TraitSpliceable implements ISpliceable { splice(start: number, deleteCount: number, elements: T[]): void { if (!this.identityProvider) { - return this.trait.splice(start, deleteCount, elements.map(e => false)); + return this.trait.splice(start, deleteCount, elements.map(() => false)); } const pastElementsWithTrait = this.trait.get().map(i => this.identityProvider!.getId(this.view.element(i)).toString()); @@ -228,7 +228,7 @@ function isInputElement(e: HTMLElement): boolean { class KeyboardController implements IDisposable { - private disposables: IDisposable[]; + private readonly disposables = new DisposableStore(); private openController: IOpenController; constructor( @@ -236,8 +236,7 @@ class KeyboardController implements IDisposable { private view: ListView, options: IListOptions ) { - const multipleSelectionSupport = !(options.multipleSelectionSupport === false); - this.disposables = []; + const multipleSelectionSupport = options.multipleSelectionSupport !== false; this.openController = options.openController || DefaultOpenController; @@ -314,7 +313,7 @@ class KeyboardController implements IDisposable { } dispose() { - this.disposables = dispose(this.disposables); + this.disposables.dispose(); } } @@ -323,42 +322,91 @@ enum TypeLabelControllerState { Typing } -class TypeLabelController implements IDisposable { - - private static mightProducePrintableCharacter(event: IKeyboardEvent): boolean { - if (event.ctrlKey || event.metaKey || event.altKey) { - return false; - } - - return (event.keyCode >= KeyCode.KEY_A && event.keyCode <= KeyCode.KEY_Z) - || (event.keyCode >= KeyCode.KEY_0 && event.keyCode <= KeyCode.KEY_9) - || (event.keyCode >= KeyCode.US_SEMICOLON && event.keyCode <= KeyCode.US_QUOTE); +export function mightProducePrintableCharacter(event: IKeyboardEvent): boolean { + if (event.ctrlKey || event.metaKey || event.altKey) { + return false; } + return (event.keyCode >= KeyCode.KEY_A && event.keyCode <= KeyCode.KEY_Z) + || (event.keyCode >= KeyCode.KEY_0 && event.keyCode <= KeyCode.KEY_9) + || (event.keyCode >= KeyCode.NUMPAD_0 && event.keyCode <= KeyCode.NUMPAD_9) + || (event.keyCode >= KeyCode.US_SEMICOLON && event.keyCode <= KeyCode.US_QUOTE); +} + +class TypeLabelController implements IDisposable { + + private enabled = false; private state: TypeLabelControllerState = TypeLabelControllerState.Idle; - private disposables: IDisposable[] = []; + + private automaticKeyboardNavigation = true; + private triggered = false; + + private readonly enabledDisposables = new DisposableStore(); + private readonly disposables = new DisposableStore(); constructor( private list: List, private view: ListView, private keyboardNavigationLabelProvider: IKeyboardNavigationLabelProvider ) { - const onChar = Event.chain(domEvent(view.domNode, 'keydown')) + this.updateOptions(list.options); + } + + updateOptions(options: IListOptions): void { + const enableKeyboardNavigation = typeof options.enableKeyboardNavigation === 'undefined' ? true : !!options.enableKeyboardNavigation; + + if (enableKeyboardNavigation) { + this.enable(); + } else { + this.disable(); + } + + if (typeof options.automaticKeyboardNavigation !== 'undefined') { + this.automaticKeyboardNavigation = options.automaticKeyboardNavigation; + } + } + + toggle(): void { + this.triggered = !this.triggered; + } + + private enable(): void { + if (this.enabled) { + return; + } + + const onChar = Event.chain(domEvent(this.view.domNode, 'keydown')) .filter(e => !isInputElement(e.target as HTMLElement)) + .filter(() => this.automaticKeyboardNavigation || this.triggered) .map(event => new StandardKeyboardEvent(event)) - .filter(keyboardNavigationLabelProvider.mightProducePrintableCharacter ? e => keyboardNavigationLabelProvider.mightProducePrintableCharacter!(e) : e => TypeLabelController.mightProducePrintableCharacter(e)) + .filter(this.keyboardNavigationLabelProvider.mightProducePrintableCharacter ? e => this.keyboardNavigationLabelProvider.mightProducePrintableCharacter!(e) : e => mightProducePrintableCharacter(e)) + .forEach(e => { e.stopPropagation(); e.preventDefault(); }) .map(event => event.browserEvent.key) .event; const onClear = Event.debounce(onChar, () => null, 800); const onInput = Event.reduce(Event.any(onChar, onClear), (r, i) => i === null ? null : ((r || '') + i)); - onInput(this.onInput, this, this.disposables); + onInput(this.onInput, this, this.enabledDisposables); + + this.enabled = true; + this.triggered = false; + } + + private disable(): void { + if (!this.enabled) { + return; + } + + this.enabledDisposables.clear(); + this.enabled = false; + this.triggered = false; } private onInput(word: string | null): void { if (!word) { this.state = TypeLabelControllerState.Idle; + this.triggered = false; return; } @@ -370,8 +418,9 @@ class TypeLabelController implements IDisposable { for (let i = 0; i < this.list.length; i++) { const index = (start + i + delta) % this.list.length; const label = this.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(this.view.element(index)); + const labelStr = label && label.toString(); - if (matchesPrefix(word, label.toString())) { + if (typeof labelStr === 'undefined' || matchesPrefix(word, labelStr)) { this.list.setFocus([index]); this.list.reveal(index); return; @@ -380,20 +429,20 @@ class TypeLabelController implements IDisposable { } dispose() { - this.disposables = dispose(this.disposables); + this.disable(); + this.enabledDisposables.dispose(); + this.disposables.dispose(); } } class DOMFocusController implements IDisposable { - private disposables: IDisposable[] = []; + private readonly disposables = new DisposableStore(); constructor( private list: List, private view: ListView ) { - this.disposables = []; - const onKeyDown = Event.chain(domEvent(view.domNode, 'keydown')) .filter(e => !isInputElement(e.target as HTMLElement)) .map(e => new StandardKeyboardEvent(e)); @@ -436,7 +485,7 @@ class DOMFocusController implements IDisposable { } dispose() { - this.disposables = dispose(this.disposables); + this.disposables.dispose(); } } @@ -452,7 +501,7 @@ function isMouseRightClick(event: UIEvent): boolean { return event instanceof MouseEvent && event.button === 2; } -const DefaultMultipleSelectionContoller = { +const DefaultMultipleSelectionController = { isSelectionSingleChangeEvent, isSelectionRangeChangeEvent }; @@ -467,35 +516,38 @@ const DefaultOpenController: IOpenController = { } }; -class MouseController implements IDisposable { +export class MouseController implements IDisposable { private multipleSelectionSupport: boolean; - private multipleSelectionController: IMultipleSelectionController; + readonly multipleSelectionController: IMultipleSelectionController | undefined; private openController: IOpenController; - private disposables: IDisposable[] = []; + private mouseSupport: boolean; + private readonly disposables = new DisposableStore(); - constructor( - private list: List, - private view: ListView, - private options: IListOptions = {} - ) { - this.multipleSelectionSupport = !(options.multipleSelectionSupport === false); + constructor(protected list: List) { + this.multipleSelectionSupport = !(list.options.multipleSelectionSupport === false); if (this.multipleSelectionSupport) { - this.multipleSelectionController = options.multipleSelectionController || DefaultMultipleSelectionContoller; + this.multipleSelectionController = list.options.multipleSelectionController || DefaultMultipleSelectionController; } - this.openController = options.openController || DefaultOpenController; + this.openController = list.options.openController || DefaultOpenController; + this.mouseSupport = typeof list.options.mouseSupport === 'undefined' || !!list.options.mouseSupport; - view.onMouseDown(this.onMouseDown, this, this.disposables); - view.onMouseClick(this.onPointer, this, this.disposables); - view.onMouseDblClick(this.onDoubleClick, this, this.disposables); - view.onTouchStart(this.onMouseDown, this, this.disposables); - view.onTap(this.onPointer, this, this.disposables); - Gesture.addTarget(view.domNode); + if (this.mouseSupport) { + list.onMouseDown(this.onMouseDown, this, this.disposables); + list.onContextMenu(this.onContextMenu, this, this.disposables); + list.onMouseDblClick(this.onDoubleClick, this, this.disposables); + list.onTouchStart(this.onMouseDown, this, this.disposables); + Gesture.addTarget(list.getHTMLElement()); + } + + list.onMouseClick(this.onPointer, this, this.disposables); + list.onMouseMiddleClick(this.onPointer, this, this.disposables); + list.onTap(this.onPointer, this, this.disposables); } - private isSelectionSingleChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { + protected isSelectionSingleChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { if (this.multipleSelectionController) { return this.multipleSelectionController.isSelectionSingleChangeEvent(event); } @@ -503,7 +555,7 @@ class MouseController implements IDisposable { return platform.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey; } - private isSelectionRangeChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { + protected isSelectionRangeChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { if (this.multipleSelectionController) { return this.multipleSelectionController.isSelectionRangeChangeEvent(event); } @@ -516,11 +568,23 @@ class MouseController implements IDisposable { } private onMouseDown(e: IListMouseEvent | IListTouchEvent): void { - if (this.options.focusOnMouseDown === false) { - e.browserEvent.preventDefault(); - e.browserEvent.stopPropagation(); - } else if (document.activeElement !== e.browserEvent.target) { - this.view.domNode.focus(); + if (document.activeElement !== e.browserEvent.target) { + this.list.domFocus(); + } + } + + private onContextMenu(e: IListContextMenuEvent): void { + const focus = typeof e.index === 'undefined' ? [] : [e.index]; + this.list.setFocus(focus, e.browserEvent); + } + + protected onPointer(e: IListMouseEvent): void { + if (!this.mouseSupport) { + return; + } + + if (isInputElement(e.browserEvent.target as HTMLElement)) { + return; } let reference = this.list.getFocus()[0]; @@ -539,15 +603,13 @@ class MouseController implements IDisposable { return this.changeSelection(e, reference); } - if (selection.every(s => s !== focus)) { - this.list.setFocus([focus], e.browserEvent); - } - if (this.multipleSelectionSupport && this.isSelectionChangeEvent(e)) { return this.changeSelection(e, reference); } - if (this.options.selectOnMouseDown && !isMouseRightClick(e.browserEvent)) { + this.list.setFocus([focus], e.browserEvent); + + if (!isMouseRightClick(e.browserEvent)) { this.list.setSelection([focus], e.browserEvent); if (this.openController.shouldOpen(e.browserEvent)) { @@ -556,22 +618,11 @@ class MouseController implements IDisposable { } } - private onPointer(e: IListMouseEvent): void { - if (this.multipleSelectionSupport && this.isSelectionChangeEvent(e)) { + private onDoubleClick(e: IListMouseEvent): void { + if (isInputElement(e.browserEvent.target as HTMLElement)) { return; } - if (!this.options.selectOnMouseDown) { - const focus = this.list.getFocus(); - this.list.setSelection(focus, e.browserEvent); - - if (this.openController.shouldOpen(e.browserEvent)) { - this.list.open(focus, e.browserEvent); - } - } - } - - private onDoubleClick(e: IListMouseEvent): void { if (this.multipleSelectionSupport && this.isSelectionChangeEvent(e)) { return; } @@ -602,6 +653,8 @@ class MouseController implements IDisposable { const selection = this.list.getSelection(); const newSelection = selection.filter(i => i !== focus); + this.list.setFocus([focus]); + if (selection.length === newSelection.length) { this.list.setSelection([...newSelection, focus], e.browserEvent); } else { @@ -611,7 +664,7 @@ class MouseController implements IDisposable { } dispose() { - this.disposables = dispose(this.disposables); + this.disposables.dispose(); } } @@ -638,9 +691,14 @@ export interface IAccessibilityProvider { * Returning null will not disable ARIA for the element. Instead it is up to the screen reader * to compute a meaningful label based on the contents of the element in the DOM * - * See also: https://www.w3.org/TR/wai-aria/states_and_properties#aria-label + * See also: https://www.w3.org/TR/wai-aria/#aria-label */ getAriaLabel(element: T): string | null; + + /** + * https://www.w3.org/TR/wai-aria/#aria-level + */ + getAriaLevel?(element: T): number | undefined; } export class DefaultStyleController implements IStyleController { @@ -670,11 +728,17 @@ export class DefaultStyleController implements IStyleController { } if (styles.listFocusAndSelectionBackground) { - content.push(`.monaco-list${suffix}:focus .monaco-list-row.selected.focused { background-color: ${styles.listFocusAndSelectionBackground}; }`); + content.push(` + .monaco-drag-image, + .monaco-list${suffix}:focus .monaco-list-row.selected.focused { background-color: ${styles.listFocusAndSelectionBackground}; } + `); } if (styles.listFocusAndSelectionForeground) { - content.push(`.monaco-list${suffix}:focus .monaco-list-row.selected.focused { color: ${styles.listFocusAndSelectionForeground}; }`); + content.push(` + .monaco-drag-image, + .monaco-list${suffix}:focus .monaco-list-row.selected.focused { color: ${styles.listFocusAndSelectionForeground}; } + `); } if (styles.listInactiveFocusBackground) { @@ -692,11 +756,11 @@ export class DefaultStyleController implements IStyleController { } if (styles.listHoverBackground) { - content.push(`.monaco-list${suffix} .monaco-list-row:hover { 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) { - content.push(`.monaco-list${suffix} .monaco-list-row:hover { color: ${styles.listHoverForeground}; }`); + content.push(`.monaco-list${suffix} .monaco-list-row:hover:not(.selected):not(.focused) { color: ${styles.listHoverForeground}; }`); } if (styles.listSelectionOutline) { @@ -704,7 +768,10 @@ export class DefaultStyleController implements IStyleController { } if (styles.listFocusOutline) { - content.push(`.monaco-list${suffix}:focus .monaco-list-row.focused { outline: 1px solid ${styles.listFocusOutline}; outline-offset: -1px; }`); + content.push(` + .monaco-drag-image, + .monaco-list${suffix}:focus .monaco-list-row.focused { outline: 1px solid ${styles.listFocusOutline}; outline-offset: -1px; } + `); } if (styles.listInactiveFocusOutline) { @@ -715,6 +782,29 @@ export class DefaultStyleController implements IStyleController { content.push(`.monaco-list${suffix} .monaco-list-row:hover { outline: 1px dashed ${styles.listHoverOutline}; outline-offset: -1px; }`); } + if (styles.listDropBackground) { + content.push(` + .monaco-list${suffix}.drop-target, + .monaco-list${suffix} .monaco-list-row.drop-target { background-color: ${styles.listDropBackground} !important; color: inherit !important; } + `); + } + + if (styles.listFilterWidgetBackground) { + content.push(`.monaco-list-type-filter { background-color: ${styles.listFilterWidgetBackground} }`); + } + + if (styles.listFilterWidgetOutline) { + content.push(`.monaco-list-type-filter { border: 1px solid ${styles.listFilterWidgetOutline}; }`); + } + + if (styles.listFilterWidgetNoMatchesOutline) { + content.push(`.monaco-list-type-filter.no-matches { border: 1px solid ${styles.listFilterWidgetNoMatchesOutline}; }`); + } + + if (styles.listMatchesShadow) { + content.push(`.monaco-list-type-filter { box-shadow: 1px 1px 1px ${styles.listMatchesShadow}; }`); + } + const newStyles = content.join('\n'); if (newStyles !== this.styleElement.innerHTML) { this.styleElement.innerHTML = newStyles; @@ -722,20 +812,29 @@ export class DefaultStyleController implements IStyleController { } } -export interface IListOptions extends IListViewOptions, IListStyles { - identityProvider?: IIdentityProvider; - keyboardNavigationLabelProvider?: IKeyboardNavigationLabelProvider; - ariaLabel?: string; - mouseSupport?: boolean; - selectOnMouseDown?: boolean; - focusOnMouseDown?: boolean; - keyboardSupport?: boolean; - verticalScrollMode?: ScrollbarVisibility; - multipleSelectionSupport?: boolean; - multipleSelectionController?: IMultipleSelectionController; - openController?: IOpenController; - styleController?: IStyleController; - accessibilityProvider?: IAccessibilityProvider; +export interface IListOptions extends IListStyles { + readonly identityProvider?: IIdentityProvider; + readonly dnd?: IListDragAndDrop; + readonly enableKeyboardNavigation?: boolean; + readonly automaticKeyboardNavigation?: boolean; + readonly keyboardNavigationLabelProvider?: IKeyboardNavigationLabelProvider; + readonly ariaRole?: ListAriaRootRole; + readonly ariaLabel?: string; + readonly keyboardSupport?: boolean; + readonly multipleSelectionSupport?: boolean; + readonly multipleSelectionController?: IMultipleSelectionController; + readonly openController?: IOpenController; + readonly styleController?: IStyleController; + readonly accessibilityProvider?: IAccessibilityProvider; + + // list view options + readonly useShadows?: boolean; + readonly verticalScrollMode?: ScrollbarVisibility; + readonly setRowLineHeight?: boolean; + readonly supportDynamicHeights?: boolean; + readonly mouseSupport?: boolean; + readonly horizontalScrolling?: boolean; + readonly ariaProvider?: IAriaProvider; } export interface IListStyles { @@ -755,6 +854,11 @@ export interface IListStyles { listInactiveFocusOutline?: Color; listSelectionOutline?: Color; listHoverOutline?: Color; + listFilterWidgetBackground?: Color; + listFilterWidgetOutline?: Color; + listFilterWidgetNoMatchesOutline?: Color; + listMatchesShadow?: Color; + treeIndentGuidesStroke?: Color; } const defaultStyles: IListStyles = { @@ -765,13 +869,21 @@ const defaultStyles: IListStyles = { listFocusAndSelectionForeground: Color.fromHex('#FFFFFF'), listInactiveSelectionBackground: Color.fromHex('#3F3F46'), listHoverBackground: Color.fromHex('#2A2D2E'), - listDropBackground: Color.fromHex('#383B3D') + listDropBackground: Color.fromHex('#383B3D'), + treeIndentGuidesStroke: Color.fromHex('#a9a9a9') }; -const DefaultOptions: IListOptions = { +const DefaultOptions = { keyboardSupport: true, mouseSupport: true, - multipleSelectionSupport: true + multipleSelectionSupport: true, + dnd: { + getDragURI() { return null; }, + onDragStart(): void { }, + onDragOver() { return false; }, + drop() { } + }, + ariaRootRole: ListAriaRootRole.TREE }; // TODO@Joao: move these utils into a SortedArray class @@ -800,7 +912,7 @@ function getContiguousRangeContaining(range: number[], value: number): number[] /** * Given two sorted collections of numbers, returns the intersection - * betweem them (OR). + * between them (OR). */ function disjunction(one: number[], other: number[]): number[] { const result: number[] = []; @@ -870,20 +982,20 @@ class PipelineRenderer implements IListRenderer { return this.renderers.map(r => r.renderTemplate(container)); } - renderElement(element: T, index: number, templateData: any[]): void { + renderElement(element: T, index: number, templateData: any[], height: number | undefined): void { let i = 0; for (const renderer of this.renderers) { - renderer.renderElement(element, index, templateData[i++]); + renderer.renderElement(element, index, templateData[i++], height); } } - disposeElement(element: T, index: number, templateData: any[]): void { + disposeElement(element: T, index: number, templateData: any[], height: number | undefined): void { let i = 0; for (const renderer of this.renderers) { if (renderer.disposeElement) { - renderer.disposeElement(element, index, templateData[i]); + renderer.disposeElement(element, index, templateData[i], height); } i += 1; @@ -903,9 +1015,7 @@ class AccessibiltyRenderer implements IListRenderer { templateId: string = 'a18n'; - constructor(private accessibilityProvider: IAccessibilityProvider) { - - } + constructor(private accessibilityProvider: IAccessibilityProvider) { } renderTemplate(container: HTMLElement): HTMLElement { return container; @@ -919,6 +1029,14 @@ class AccessibiltyRenderer implements IListRenderer { } else { container.removeAttribute('aria-label'); } + + const ariaLevel = this.accessibilityProvider.getAriaLevel && this.accessibilityProvider.getAriaLevel(element); + + if (typeof ariaLevel === 'number') { + container.setAttribute('aria-level', `${ariaLevel}`); + } else { + container.removeAttribute('aria-level'); + } } disposeTemplate(templateData: any): void { @@ -926,19 +1044,60 @@ class AccessibiltyRenderer implements IListRenderer { } } -export class List implements ISpliceable, IDisposable { +class ListViewDragAndDrop implements IListViewDragAndDrop { - private static InstanceCount = 0; - private idPrefix = `list_id_${++List.InstanceCount}`; + constructor(private list: List, private dnd: IListDragAndDrop) { } + + getDragElements(element: T): T[] { + const selection = this.list.getSelectedElements(); + const elements = selection.indexOf(element) > -1 ? selection : [element]; + return elements; + } + + getDragURI(element: T): string | null { + return this.dnd.getDragURI(element); + } + + getDragLabel?(elements: T[]): string | undefined { + if (this.dnd.getDragLabel) { + return this.dnd.getDragLabel(elements); + } + + return undefined; + } + + onDragStart(data: IDragAndDropData, originalEvent: DragEvent): void { + if (this.dnd.onDragStart) { + this.dnd.onDragStart(data, originalEvent); + } + } + + onDragOver(data: IDragAndDropData, targetElement: T, targetIndex: number, originalEvent: DragEvent): boolean | IListDragOverReaction { + return this.dnd.onDragOver(data, targetElement, targetIndex, originalEvent); + } + + drop(data: IDragAndDropData, targetElement: T, targetIndex: number, originalEvent: DragEvent): void { + this.dnd.drop(data, targetElement, targetIndex, originalEvent); + } +} + +export interface IListOptionsUpdate { + readonly enableKeyboardNavigation?: boolean; + readonly automaticKeyboardNavigation?: boolean; +} + +export class List implements ISpliceable, IDisposable { private focus: Trait; private selection: Trait; private eventBufferer = new EventBufferer(); private view: ListView; private spliceable: ISpliceable; - protected disposables: IDisposable[]; private styleElement: HTMLStyleElement; private styleController: IStyleController; + private typeLabelController?: TypeLabelController; + + protected readonly disposables = new DisposableStore(); @memoize get onFocusChange(): Event> { return Event.map(this.eventBufferer.wrapEvent(this.focus.onChange), e => this.toListEvent(e)); @@ -956,6 +1115,8 @@ export class List implements ISpliceable, IDisposable { return Event.map(this._onPin.event, indexes => this.toListEvent({ indexes })); } + get domId(): string { return this.view.domId; } + get onDidScroll(): Event { return this.view.onDidScroll; } get onMouseClick(): Event> { return this.view.onMouseClick; } get onMouseDblClick(): Event> { return this.view.onMouseDblClick; } get onMouseMiddleClick(): Event> { return this.view.onMouseMiddleClick; } @@ -973,13 +1134,7 @@ export class List implements ISpliceable, IDisposable { .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; }) - .map(event => { - const index = this.getFocus()[0]; - const element = this.view.element(index); - const anchor = this.view.domElement(index) || undefined; - return { index, element, anchor, browserEvent: event.browserEvent }; - }) - .event; + .event as Event; const fromKeyup = Event.chain(domEvent(this.view.domNode, 'keyup')) .filter(() => { @@ -987,14 +1142,13 @@ export class List implements ISpliceable, IDisposable { this.didJustPressContextMenuKey = false; return didJustPressContextMenuKey; }) - .filter(() => this.getFocus().length > 0) + .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) || undefined; + const anchor = this.view.domElement(index) as HTMLElement; return { index, element, anchor, browserEvent }; }) - .filter(({ anchor }) => !!anchor) .event; const fromMouse = Event.chain(this.view.onContextMenu) @@ -1013,71 +1167,96 @@ export class List implements ISpliceable, IDisposable { readonly onDidBlur: Event; private _onDidDispose = new Emitter(); - get onDidDispose(): Event { return this._onDidDispose.event; } + readonly onDidDispose: Event = this._onDidDispose.event; constructor( container: HTMLElement, virtualDelegate: IListVirtualDelegate, renderers: IListRenderer[], - options: IListOptions = DefaultOptions + private _options: IListOptions = DefaultOptions ) { - this.focus = new FocusTrait(i => this.getElementDomId(i)); + this.focus = new FocusTrait(); this.selection = new Trait('selected'); - mixin(options, defaultStyles, false); + mixin(_options, defaultStyles, false); const baseRenderers: IListRenderer[] = [this.focus.renderer, this.selection.renderer]; - if (options.accessibilityProvider) { - baseRenderers.push(new AccessibiltyRenderer(options.accessibilityProvider)); + if (_options.accessibilityProvider) { + baseRenderers.push(new AccessibiltyRenderer(_options.accessibilityProvider)); } renderers = renderers.map(r => new PipelineRenderer(r.templateId, [...baseRenderers, r])); - this.view = new ListView(container, virtualDelegate, renderers, options); - this.view.domNode.setAttribute('role', 'tree'); - DOM.addClass(this.view.domNode, this.idPrefix); - this.view.domNode.tabIndex = 0; + const viewOptions: IListViewOptions = { + ..._options, + dnd: _options.dnd && new ListViewDragAndDrop(this, _options.dnd) + }; + + this.view = new ListView(container, virtualDelegate, renderers, viewOptions); + + if (typeof _options.ariaRole !== 'string') { + this.view.domNode.setAttribute('role', ListAriaRootRole.TREE); + } else { + this.view.domNode.setAttribute('role', _options.ariaRole); + } this.styleElement = DOM.createStyleSheet(this.view.domNode); - this.styleController = options.styleController || new DefaultStyleController(this.styleElement, this.idPrefix); + this.styleController = _options.styleController || new DefaultStyleController(this.styleElement, this.view.domId); this.spliceable = new CombinedSpliceable([ - new TraitSpliceable(this.focus, this.view, options.identityProvider), - new TraitSpliceable(this.selection, this.view, options.identityProvider), + new TraitSpliceable(this.focus, this.view, _options.identityProvider), + new TraitSpliceable(this.selection, this.view, _options.identityProvider), this.view ]); - this.disposables = [this.focus, this.selection, this.view, this._onDidDispose]; + this.disposables.add(this.focus); + this.disposables.add(this.selection); + this.disposables.add(this.view); + this.disposables.add(this._onDidDispose); this.onDidFocus = Event.map(domEvent(this.view.domNode, 'focus', true), () => null!); this.onDidBlur = Event.map(domEvent(this.view.domNode, 'blur', true), () => null!); - this.disposables.push(new DOMFocusController(this, this.view)); + this.disposables.add(new DOMFocusController(this, this.view)); - if (typeof options.keyboardSupport !== 'boolean' || options.keyboardSupport) { - const controller = new KeyboardController(this, this.view, options); - this.disposables.push(controller); + if (typeof _options.keyboardSupport !== 'boolean' || _options.keyboardSupport) { + const controller = new KeyboardController(this, this.view, _options); + this.disposables.add(controller); } - if (options.keyboardNavigationLabelProvider) { - const controller = new TypeLabelController(this, this.view, options.keyboardNavigationLabelProvider); - this.disposables.push(controller); + if (_options.keyboardNavigationLabelProvider) { + this.typeLabelController = new TypeLabelController(this, this.view, _options.keyboardNavigationLabelProvider); + this.disposables.add(this.typeLabelController); } - if (typeof options.mouseSupport === 'boolean' ? options.mouseSupport : true) { - this.disposables.push(new MouseController(this, this.view, options)); - } + this.disposables.add(this.createMouseController(_options)); this.onFocusChange(this._onFocusChange, this, this.disposables); this.onSelectionChange(this._onSelectionChange, this, this.disposables); - if (options.ariaLabel) { - this.view.domNode.setAttribute('aria-label', localize('aria list', "{0}. Use the navigation keys to navigate.", options.ariaLabel)); + if (_options.ariaLabel) { + this.view.domNode.setAttribute('aria-label', localize('aria list', "{0}. Use the navigation keys to navigate.", _options.ariaLabel)); } - this.style(options); + this.style(_options); + } + + protected createMouseController(options: IListOptions): MouseController { + return new MouseController(this); + } + + updateOptions(optionsUpdate: IListOptionsUpdate = {}): void { + this._options = { ...this._options, ...optionsUpdate }; + + if (this.typeLabelController) { + this.typeLabelController.updateOptions(this._options); + } + } + + get options(): IListOptions { + return this._options; } splice(start: number, deleteCount: number, elements: T[] = []): void { @@ -1096,6 +1275,14 @@ export class List implements ISpliceable, IDisposable { this.eventBufferer.bufferEvents(() => this.spliceable.splice(start, deleteCount, elements)); } + updateWidth(index: number): void { + this.view.updateWidth(index); + } + + rerender(): void { + this.view.rerender(); + } + element(index: number): T { return this.view.element(index); } @@ -1128,16 +1315,26 @@ export class List implements ISpliceable, IDisposable { return this.view.renderHeight; } + get firstVisibleIndex(): number { + return this.view.firstVisibleIndex; + } + + get lastVisibleIndex(): number { + return this.view.lastVisibleIndex; + } + domFocus(): void { this.view.domNode.focus(); } - layout(height?: number): void { - this.view.layout(height); + layout(height?: number, width?: number): void { + this.view.layout(height, width); } - layoutWidth(width: number): void { - this.view.layoutWidth(width); + toggleKeyboardNavigation(): void { + if (this.typeLabelController) { + this.typeLabelController.toggle(); + } } setSelection(indexes: number[], browserEvent?: UIEvent): void { @@ -1147,7 +1344,6 @@ export class List implements ISpliceable, IDisposable { } } - indexes = indexes.sort(numericSort); this.selection.set(indexes, browserEvent); } @@ -1166,45 +1362,57 @@ export class List implements ISpliceable, IDisposable { } } - indexes = indexes.sort(numericSort); this.focus.set(indexes, browserEvent); } - focusNext(n = 1, loop = false, browserEvent?: UIEvent): void { + focusNext(n = 1, loop = false, browserEvent?: UIEvent, filter?: (element: T) => boolean): void { if (this.length === 0) { return; } + const focus = this.focus.get(); - let index = focus.length > 0 ? focus[0] + n : 0; - this.setFocus(loop ? [index % this.length] : [Math.min(index, this.length - 1)], browserEvent); + const index = this.findNextIndex(focus.length > 0 ? focus[0] + n : 0, loop, filter); + + if (index > -1) { + this.setFocus([index], browserEvent); + } } - focusPrevious(n = 1, loop = false, browserEvent?: UIEvent): void { + focusPrevious(n = 1, loop = false, browserEvent?: UIEvent, filter?: (element: T) => boolean): void { if (this.length === 0) { return; } + const focus = this.focus.get(); - let index = focus.length > 0 ? focus[0] - n : 0; - if (loop && index < 0) { index = (this.length + (index % this.length)) % this.length; } - this.setFocus([Math.max(index, 0)], browserEvent); + const index = this.findPreviousIndex(focus.length > 0 ? focus[0] - n : 0, loop, filter); + + if (index > -1) { + this.setFocus([index], browserEvent); + } } - focusNextPage(browserEvent?: UIEvent): void { + focusNextPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): void { let lastPageIndex = this.view.indexAt(this.view.getScrollTop() + this.view.renderHeight); lastPageIndex = lastPageIndex === 0 ? 0 : lastPageIndex - 1; const lastPageElement = this.view.element(lastPageIndex); const currentlyFocusedElement = this.getFocusedElements()[0]; if (currentlyFocusedElement !== lastPageElement) { - this.setFocus([lastPageIndex], browserEvent); + const lastGoodPageIndex = this.findPreviousIndex(lastPageIndex, false, filter); + + if (lastGoodPageIndex > -1 && currentlyFocusedElement !== this.view.element(lastGoodPageIndex)) { + this.setFocus([lastGoodPageIndex], browserEvent); + } else { + this.setFocus([lastPageIndex], browserEvent); + } } else { const previousScrollTop = this.view.getScrollTop(); this.view.setScrollTop(previousScrollTop + this.view.renderHeight - this.view.elementHeight(lastPageIndex)); if (this.view.getScrollTop() !== previousScrollTop) { // Let the scroll event listener run - setTimeout(() => this.focusNextPage(browserEvent), 0); + setTimeout(() => this.focusNextPage(browserEvent, filter), 0); } } } - focusPreviousPage(browserEvent?: UIEvent): void { + focusPreviousPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): void { let firstPageIndex: number; const scrollTop = this.view.getScrollTop(); @@ -1218,26 +1426,78 @@ export class List implements ISpliceable, IDisposable { const currentlyFocusedElement = this.getFocusedElements()[0]; if (currentlyFocusedElement !== firstPageElement) { - this.setFocus([firstPageIndex], browserEvent); + const firstGoodPageIndex = this.findNextIndex(firstPageIndex, false, filter); + + if (firstGoodPageIndex > -1 && currentlyFocusedElement !== this.view.element(firstGoodPageIndex)) { + this.setFocus([firstGoodPageIndex], browserEvent); + } else { + this.setFocus([firstPageIndex], browserEvent); + } } else { const previousScrollTop = scrollTop; this.view.setScrollTop(scrollTop - this.view.renderHeight); if (this.view.getScrollTop() !== previousScrollTop) { // Let the scroll event listener run - setTimeout(() => this.focusPreviousPage(browserEvent), 0); + setTimeout(() => this.focusPreviousPage(browserEvent, filter), 0); } } } - focusLast(browserEvent?: UIEvent): void { + focusLast(browserEvent?: UIEvent, filter?: (element: T) => boolean): void { if (this.length === 0) { return; } - this.setFocus([this.length - 1], browserEvent); + + const index = this.findPreviousIndex(this.length - 1, false, filter); + + if (index > -1) { + this.setFocus([index], browserEvent); + } } - focusFirst(browserEvent?: UIEvent): void { + focusFirst(browserEvent?: UIEvent, filter?: (element: T) => boolean): void { if (this.length === 0) { return; } - this.setFocus([0], browserEvent); + + const index = this.findNextIndex(0, false, filter); + + if (index > -1) { + this.setFocus([index], browserEvent); + } + } + + private findNextIndex(index: number, loop = false, filter?: (element: T) => boolean): number { + for (let i = 0; i < this.length; i++) { + if (index >= this.length && !loop) { + return -1; + } + + index = index % this.length; + + if (!filter || filter(this.element(index))) { + return index; + } + + index++; + } + + return -1; + } + + private findPreviousIndex(index: number, loop = false, filter?: (element: T) => boolean): number { + for (let i = 0; i < this.length; i++) { + if (index < 0 && !loop) { + return -1; + } + + index = (this.length + (index % this.length)) % this.length; + + if (!filter || filter(this.element(index))) { + return index; + } + + index--; + } + + return -1; } getFocus(): number[] { @@ -1295,10 +1555,6 @@ export class List implements ISpliceable, IDisposable { return Math.abs((scrollTop - elementTop) / m); } - private getElementDomId(index: number): string { - return `${this.idPrefix}_${index}`; - } - isDOMFocused(): boolean { return this.view.domNode === document.activeElement; } @@ -1339,7 +1595,7 @@ export class List implements ISpliceable, IDisposable { const focus = this.focus.get(); if (focus.length > 0) { - this.view.domNode.setAttribute('aria-activedescendant', this.getElementDomId(focus[0])); + this.view.domNode.setAttribute('aria-activedescendant', this.view.getElementDomId(focus[0])); } else { this.view.domNode.removeAttribute('aria-activedescendant'); } @@ -1358,7 +1614,7 @@ export class List implements ISpliceable, IDisposable { dispose(): void { this._onDidDispose.fire(); - this.disposables = dispose(this.disposables); + this.disposables.dispose(); this._onDidOpen.dispose(); this._onPin.dispose(); diff --git a/src/vs/base/browser/ui/list/media/close-dark.svg b/src/vs/base/browser/ui/list/media/close-dark.svg new file mode 100644 index 00000000000..7305a8f099a --- /dev/null +++ b/src/vs/base/browser/ui/list/media/close-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/list/media/close-hc.svg b/src/vs/base/browser/ui/list/media/close-hc.svg new file mode 100644 index 00000000000..7305a8f099a --- /dev/null +++ b/src/vs/base/browser/ui/list/media/close-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/list/media/close-light.svg b/src/vs/base/browser/ui/list/media/close-light.svg new file mode 100644 index 00000000000..ecddcd665b5 --- /dev/null +++ b/src/vs/base/browser/ui/list/media/close-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/list/media/filter-dark.svg b/src/vs/base/browser/ui/list/media/filter-dark.svg new file mode 100644 index 00000000000..46c35f4374d --- /dev/null +++ b/src/vs/base/browser/ui/list/media/filter-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/list/media/filter-hc.svg b/src/vs/base/browser/ui/list/media/filter-hc.svg new file mode 100644 index 00000000000..d7b6bdd3923 --- /dev/null +++ b/src/vs/base/browser/ui/list/media/filter-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/list/media/filter-light.svg b/src/vs/base/browser/ui/list/media/filter-light.svg new file mode 100644 index 00000000000..2550d80cb70 --- /dev/null +++ b/src/vs/base/browser/ui/list/media/filter-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/list/media/no-filter-dark.svg b/src/vs/base/browser/ui/list/media/no-filter-dark.svg new file mode 100644 index 00000000000..6fc07d81a55 --- /dev/null +++ b/src/vs/base/browser/ui/list/media/no-filter-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/list/media/no-filter-hc.svg b/src/vs/base/browser/ui/list/media/no-filter-hc.svg new file mode 100644 index 00000000000..6fc07d81a55 --- /dev/null +++ b/src/vs/base/browser/ui/list/media/no-filter-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/list/media/no-filter-light.svg b/src/vs/base/browser/ui/list/media/no-filter-light.svg new file mode 100644 index 00000000000..3608b15d29e --- /dev/null +++ b/src/vs/base/browser/ui/list/media/no-filter-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/list/rangeMap.ts b/src/vs/base/browser/ui/list/rangeMap.ts index 45b164c5392..1bf7217d0af 100644 --- a/src/vs/base/browser/ui/list/rangeMap.ts +++ b/src/vs/base/browser/ui/list/rangeMap.ts @@ -84,7 +84,7 @@ export function consolidate(groups: IRangedGroup[]): IRangedGroup[] { * collection. */ function concat(...groups: IRangedGroup[][]): IRangedGroup[] { - return consolidate(groups.reduce((r, g) => r.concat(g), [] as IRangedGroup[])); + return consolidate(groups.reduce((r, g) => r.concat(g), [])); } export class RangeMap { @@ -190,4 +190,4 @@ export class RangeMap { dispose() { this.groups = null!; // StrictNullOverride: nulling out ok in dispose } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/list/rowCache.ts b/src/vs/base/browser/ui/list/rowCache.ts index b7007c2fc0f..dd54c73a0a7 100644 --- a/src/vs/base/browser/ui/list/rowCache.ts +++ b/src/vs/base/browser/ui/list/rowCache.ts @@ -38,7 +38,7 @@ export class RowCache implements IDisposable { if (!result) { const domNode = $('.monaco-list-row'); - const renderer = this.renderers.get(templateId); + const renderer = this.getRenderer(templateId); const templateData = renderer.renderTemplate(domNode); result = { domNode, templateId, templateData }; } @@ -86,7 +86,7 @@ export class RowCache implements IDisposable { this.cache.forEach((cachedRows, templateId) => { for (const cachedRow of cachedRows) { - const renderer = this.renderers.get(templateId); + const renderer = this.getRenderer(templateId); renderer.disposeTemplate(cachedRow.templateData); cachedRow.domNode = null; cachedRow.templateData = null; @@ -101,4 +101,12 @@ export class RowCache implements IDisposable { this.cache.clear(); this.renderers = null!; // StrictNullOverride: nulling out ok in dispose } + + private getRenderer(templateId: string): IListRenderer { + const renderer = this.renderers.get(templateId); + if (!renderer) { + throw new Error(`No renderer found for ${templateId}`); + } + return renderer; + } } \ No newline at end of file diff --git a/src/vs/base/browser/ui/menu/check.svg b/src/vs/base/browser/ui/menu/check.svg index 3f365c4800e..865cc83c347 100644 --- a/src/vs/base/browser/ui/menu/check.svg +++ b/src/vs/base/browser/ui/menu/check.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/src/vs/base/browser/ui/menu/ellipsis.svg b/src/vs/base/browser/ui/menu/ellipsis.svg index e3f85623356..2c52e359f61 100644 --- a/src/vs/base/browser/ui/menu/ellipsis.svg +++ b/src/vs/base/browser/ui/menu/ellipsis.svg @@ -1 +1,5 @@ -Ellipsis_bold_16x \ No newline at end of file + + + + + diff --git a/src/vs/base/browser/ui/menu/menu.css b/src/vs/base/browser/ui/menu/menu.css index 14ced9b853a..cbd6ce1a92e 100644 --- a/src/vs/base/browser/ui/menu/menu.css +++ b/src/vs/base/browser/ui/menu/menu.css @@ -117,7 +117,6 @@ /* Context Menu */ .context-view.monaco-menu-container { - font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif; outline: 0; border: none; -webkit-animation: fadeIn 0.083s linear; @@ -134,7 +133,7 @@ } .monaco-menu .monaco-action-bar.vertical .action-item { - border: 1px solid transparent; /* prevents jumping behaviour on hover or focus */ + border: thin solid transparent; /* prevents jumping behaviour on hover or focus */ } @@ -182,7 +181,6 @@ } .menubar .menubar-menu-items-holder.monaco-menu-container { - font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif; outline: 0; border: none; } diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index 25000d5e791..c2b60a5dc92 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -7,27 +7,41 @@ import 'vs/css!./menu'; import * as nls from 'vs/nls'; import * as strings from 'vs/base/common/strings'; import { IActionRunner, IAction, Action } from 'vs/base/common/actions'; -import { ActionBar, IActionItemProvider, ActionsOrientation, Separator, ActionItem, IActionItemOptions, BaseActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; -import { ResolvedKeybinding, KeyCode, KeyCodeUtils } from 'vs/base/common/keyCodes'; +import { ActionBar, IActionViewItemProvider, ActionsOrientation, Separator, ActionViewItem, IActionViewItemOptions, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; +import { ResolvedKeybinding, KeyCode } from 'vs/base/common/keyCodes'; import { addClass, EventType, EventHelper, EventLike, removeTabIndexAndUpdateFocus, isAncestor, hasClass, addDisposableListener, removeClass, append, $, addClasses, removeClasses } from 'vs/base/browser/dom'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { Color } from 'vs/base/common/color'; import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable'; import { Event, Emitter } from 'vs/base/common/event'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; -import { isLinux } from 'vs/base/common/platform'; +import { isLinux, isMacintosh } from 'vs/base/common/platform'; -export const MENU_MNEMONIC_REGEX: RegExp = /\(&{1,2}(.)\)|&{1,2}(.)/; -export const MENU_ESCAPED_MNEMONIC_REGEX: RegExp = /(?:&){1,2}(.)/; +function createMenuMnemonicRegExp() { + try { + return new RegExp('\\(&([^\\s&])\\)|(? ResolvedKeybinding | null; + getKeyBinding?: (action: IAction) => ResolvedKeybinding | undefined; ariaLabel?: string; enableMnemonics?: boolean; anchorAlignment?: AnchorAlignment; @@ -45,7 +59,7 @@ export interface IMenuStyles { } export class SubmenuAction extends Action { - constructor(label: string, public entries: Array, cssClass?: string) { + constructor(label: string, public entries: ReadonlyArray, cssClass?: string) { super(!!cssClass ? cssClass : 'submenu', label, '', true); } } @@ -56,16 +70,15 @@ interface ISubMenuData { } export class Menu extends ActionBar { - private mnemonics: Map>; - private menuDisposables: IDisposable[]; + private mnemonics: Map>; + private readonly menuDisposables: DisposableStore; private scrollableElement: DomScrollableElement; private menuElement: HTMLElement; private scrollTopHold: number | undefined; private readonly _onScroll: Emitter; - constructor(container: HTMLElement, actions: IAction[], options: IMenuOptions = {}) { - + constructor(container: HTMLElement, actions: ReadonlyArray, options: IMenuOptions = {}) { addClass(container, 'monaco-menu-container'); container.setAttribute('role', 'presentation'); const menuElement = document.createElement('div'); @@ -74,11 +87,11 @@ export class Menu extends ActionBar { super(menuElement, { orientation: ActionsOrientation.VERTICAL, - actionItemProvider: action => this.doGetActionItem(action, options, parentData), + actionViewItemProvider: action => this.doGetActionViewItem(action, options, parentData), context: options.context, actionRunner: options.actionRunner, ariaLabel: options.ariaLabel, - triggerKeys: { keys: [KeyCode.Enter], keyDown: true } + triggerKeys: { keys: [KeyCode.Enter, ...(isMacintosh ? [KeyCode.Space] : [])], keyDown: true } }); this.menuElement = menuElement; @@ -89,17 +102,26 @@ export class Menu extends ActionBar { this.actionsList.tabIndex = 0; - this.menuDisposables = []; + this.menuDisposables = this._register(new DisposableStore()); + + addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => { + const event = new StandardKeyboardEvent(e); + + // Stop tab navigation of menus + if (event.equals(KeyCode.Tab)) { + e.preventDefault(); + } + }); if (options.enableMnemonics) { - this.menuDisposables.push(addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => { - const key = KeyCodeUtils.fromString(e.key); + this.menuDisposables.add(addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => { + const key = e.key.toLocaleLowerCase(); if (this.mnemonics.has(key)) { EventHelper.stop(e, true); - const actions = this.mnemonics.get(key); + const actions = this.mnemonics.get(key)!; if (actions.length === 1) { - if (actions[0] instanceof SubmenuActionItem) { + if (actions[0] instanceof SubmenuMenuActionViewItem) { this.focusItemByElement(actions[0].container); } @@ -124,7 +146,7 @@ export class Menu extends ActionBar { const event = new StandardKeyboardEvent(e); if (event.equals(KeyCode.Home) || event.equals(KeyCode.PageUp)) { - this.focusedItem = this.items.length - 1; + this.focusedItem = this.viewItems.length - 1; this.focusNext(); EventHelper.stop(e, true); } else if (event.equals(KeyCode.End) || event.equals(KeyCode.PageDown)) { @@ -175,7 +197,7 @@ export class Menu extends ActionBar { parent: this }; - this.mnemonics = new Map>(); + this.mnemonics = new Map>(); this.push(actions, { icon: true, label: true, isMenu: true }); @@ -194,9 +216,9 @@ export class Menu extends ActionBar { menuElement.style.maxHeight = `${Math.max(10, window.innerHeight - container.getBoundingClientRect().top - 30)}px`; - this.scrollableElement.onScroll(() => { + this.menuDisposables.add(this.scrollableElement.onScroll(() => { this._onScroll.fire(); - }, this, this.menuDisposables); + }, this)); this._register(addDisposableListener(this.menuElement, EventType.SCROLL, (e: ScrollEvent) => { if (this.scrollTopHold !== undefined) { @@ -209,7 +231,7 @@ export class Menu extends ActionBar { container.appendChild(this.scrollableElement.getDomNode()); this.scrollableElement.scanDomNode(); - this.items.filter(item => !(item instanceof MenuSeparatorActionItem)).forEach((item: MenuActionItem, index: number, array: any[]) => { + this.viewItems.filter(item => !(item instanceof MenuSeparatorActionViewItem)).forEach((item: BaseMenuActionViewItem, index: number, array: any[]) => { item.updatePositionInSet(index + 1, array.length); }); } @@ -227,9 +249,9 @@ export class Menu extends ActionBar { this.domNode.style.backgroundColor = bgColor; container.style.boxShadow = shadow; - if (this.items) { - this.items.forEach(item => { - if (item instanceof MenuActionItem || item instanceof MenuSeparatorActionItem) { + if (this.viewItems) { + this.viewItems.forEach(item => { + if (item instanceof BaseMenuActionViewItem || item instanceof MenuSeparatorActionViewItem) { item.style(style); } }); @@ -249,12 +271,12 @@ export class Menu extends ActionBar { } trigger(index: number): void { - if (index <= this.items.length && index >= 0) { - const item = this.items[index]; - if (item instanceof SubmenuActionItem) { + if (index <= this.viewItems.length && index >= 0) { + const item = this.viewItems[index]; + if (item instanceof SubmenuMenuActionViewItem) { super.focus(index); item.open(true); - } else if (item instanceof MenuActionItem) { + } else if (item instanceof BaseMenuActionViewItem) { super.run(item._action, item._context); } else { return; @@ -281,27 +303,27 @@ export class Menu extends ActionBar { } } - private doGetActionItem(action: IAction, options: IMenuOptions, parentData: ISubMenuData): BaseActionItem { + private doGetActionViewItem(action: IAction, options: IMenuOptions, parentData: ISubMenuData): BaseActionViewItem { if (action instanceof Separator) { - return new MenuSeparatorActionItem(options.context, action, { icon: true }); + return new MenuSeparatorActionViewItem(options.context, action, { icon: true }); } else if (action instanceof SubmenuAction) { - const menuActionItem = new SubmenuActionItem(action, action.entries, parentData, options); + const menuActionViewItem = new SubmenuMenuActionViewItem(action, action.entries, parentData, options); if (options.enableMnemonics) { - const mnemonic = menuActionItem.getMnemonic(); - if (mnemonic && menuActionItem.isEnabled()) { - let actionItems: MenuActionItem[] = []; + const mnemonic = menuActionViewItem.getMnemonic(); + if (mnemonic && menuActionViewItem.isEnabled()) { + let actionViewItems: BaseMenuActionViewItem[] = []; if (this.mnemonics.has(mnemonic)) { - actionItems = this.mnemonics.get(mnemonic); + actionViewItems = this.mnemonics.get(mnemonic)!; } - actionItems.push(menuActionItem); + actionViewItems.push(menuActionViewItem); - this.mnemonics.set(mnemonic, actionItems); + this.mnemonics.set(mnemonic, actionViewItems); } } - return menuActionItem; + return menuActionViewItem; } else { const menuItemOptions: IMenuItemOptions = { enableMnemonics: options.enableMnemonics }; if (options.getKeyBinding) { @@ -315,32 +337,32 @@ export class Menu extends ActionBar { } } - const menuActionItem = new MenuActionItem(options.context, action, menuItemOptions); + const menuActionViewItem = new BaseMenuActionViewItem(options.context, action, menuItemOptions); if (options.enableMnemonics) { - const mnemonic = menuActionItem.getMnemonic(); - if (mnemonic && menuActionItem.isEnabled()) { - let actionItems: MenuActionItem[] = []; + const mnemonic = menuActionViewItem.getMnemonic(); + if (mnemonic && menuActionViewItem.isEnabled()) { + let actionViewItems: BaseMenuActionViewItem[] = []; if (this.mnemonics.has(mnemonic)) { - actionItems = this.mnemonics.get(mnemonic); + actionViewItems = this.mnemonics.get(mnemonic)!; } - actionItems.push(menuActionItem); + actionViewItems.push(menuActionViewItem); - this.mnemonics.set(mnemonic, actionItems); + this.mnemonics.set(mnemonic, actionViewItems); } } - return menuActionItem; + return menuActionViewItem; } } } -interface IMenuItemOptions extends IActionItemOptions { +interface IMenuItemOptions extends IActionViewItemOptions { enableMnemonics?: boolean; } -class MenuActionItem extends BaseActionItem { +class BaseMenuActionViewItem extends BaseActionViewItem { public container: HTMLElement; @@ -349,7 +371,7 @@ class MenuActionItem extends BaseActionItem { private label: HTMLElement; private check: HTMLElement; - private mnemonic: KeyCode; + private mnemonic: string; private cssClass: string; protected menuStyle: IMenuStyles; @@ -368,7 +390,7 @@ class MenuActionItem extends BaseActionItem { if (label) { let matches = MENU_MNEMONIC_REGEX.exec(label); if (matches) { - this.mnemonic = KeyCodeUtils.fromString((!!matches[1] ? matches[1] : matches[2]).toLocaleLowerCase()); + this.mnemonic = (!!matches[1] ? matches[1] : matches[2]).toLocaleLowerCase(); } } } @@ -440,13 +462,16 @@ class MenuActionItem extends BaseActionItem { label = cleanLabel; } - this.label.setAttribute('aria-label', cleanLabel); + this.label.setAttribute('aria-label', cleanLabel.replace(/&&/g, '&')); const matches = MENU_MNEMONIC_REGEX.exec(label); if (matches) { label = strings.escape(label).replace(MENU_ESCAPED_MNEMONIC_REGEX, ''); + label = label.replace(/&&/g, '&'); this.item.setAttribute('aria-keyshortcuts', (!!matches[1] ? matches[1] : matches[2]).toLocaleLowerCase()); + } else { + label = label.replace(/&&/g, '&'); } } @@ -519,7 +544,7 @@ class MenuActionItem extends BaseActionItem { } } - getMnemonic(): KeyCode { + getMnemonic(): string { return this.mnemonic; } @@ -531,7 +556,7 @@ class MenuActionItem extends BaseActionItem { const isSelected = this.element && hasClass(this.element, 'focused'); const fgColor = isSelected && this.menuStyle.selectionForegroundColor ? this.menuStyle.selectionForegroundColor : this.menuStyle.foregroundColor; const bgColor = isSelected && this.menuStyle.selectionBackgroundColor ? this.menuStyle.selectionBackgroundColor : this.menuStyle.backgroundColor; - const border = isSelected && this.menuStyle.selectionBorderColor ? `1px solid ${this.menuStyle.selectionBorderColor}` : null; + const border = isSelected && this.menuStyle.selectionBorderColor ? `thin solid ${this.menuStyle.selectionBorderColor}` : null; this.item.style.color = fgColor ? `${fgColor}` : null; this.check.style.backgroundColor = fgColor ? `${fgColor}` : null; @@ -545,18 +570,18 @@ class MenuActionItem extends BaseActionItem { } } -class SubmenuActionItem extends MenuActionItem { +class SubmenuMenuActionViewItem extends BaseMenuActionViewItem { private mysubmenu: Menu | null; private submenuContainer: HTMLElement | undefined; private submenuIndicator: HTMLElement; - private submenuDisposables: IDisposable[] = []; + private readonly submenuDisposables = this._register(new DisposableStore()); private mouseOver: boolean; private showScheduler: RunOnceScheduler; private hideScheduler: RunOnceScheduler; constructor( action: IAction, - private submenuActions: IAction[], + private submenuActions: ReadonlyArray, private parentData: ISubMenuData, private submenuOptions?: IMenuOptions ) { @@ -601,8 +626,11 @@ class SubmenuActionItem extends MenuActionItem { this._register(addDisposableListener(this.element, EventType.KEY_DOWN, e => { let event = new StandardKeyboardEvent(e); - if (event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Enter)) { - EventHelper.stop(e, true); + + if (document.activeElement === this.item) { + if (event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Enter)) { + EventHelper.stop(e, true); + } } })); @@ -649,7 +677,7 @@ class SubmenuActionItem extends MenuActionItem { this.parentData.submenu = undefined; if (this.submenuContainer) { - this.submenuDisposables = dispose(this.submenuDisposables); + this.submenuDisposables.clear(); this.submenuContainer = undefined; } } @@ -682,7 +710,7 @@ class SubmenuActionItem extends MenuActionItem { this.submenuContainer.style.top = `${this.element.offsetTop - this.parentData.parent.scrollOffset - paddingTop}px`; } - this.submenuDisposables.push(addDisposableListener(this.submenuContainer, EventType.KEY_UP, e => { + this.submenuDisposables.add(addDisposableListener(this.submenuContainer, EventType.KEY_UP, e => { let event = new StandardKeyboardEvent(e); if (event.equals(KeyCode.LeftArrow)) { EventHelper.stop(e, true); @@ -694,12 +722,12 @@ class SubmenuActionItem extends MenuActionItem { this.parentData.submenu = undefined; } - this.submenuDisposables = dispose(this.submenuDisposables); + this.submenuDisposables.clear(); this.submenuContainer = undefined; } })); - this.submenuDisposables.push(addDisposableListener(this.submenuContainer, EventType.KEY_DOWN, e => { + this.submenuDisposables.add(addDisposableListener(this.submenuContainer, EventType.KEY_DOWN, e => { let event = new StandardKeyboardEvent(e); if (event.equals(KeyCode.LeftArrow)) { EventHelper.stop(e, true); @@ -707,7 +735,7 @@ class SubmenuActionItem extends MenuActionItem { })); - this.submenuDisposables.push(this.parentData.submenu.onDidCancel(() => { + this.submenuDisposables.add(this.parentData.submenu.onDidCancel(() => { this.parentData.parent.focus(); if (this.parentData.submenu) { @@ -715,7 +743,7 @@ class SubmenuActionItem extends MenuActionItem { this.parentData.submenu = undefined; } - this.submenuDisposables = dispose(this.submenuDisposables); + this.submenuDisposables.clear(); this.submenuContainer = undefined; })); @@ -755,13 +783,12 @@ class SubmenuActionItem extends MenuActionItem { } if (this.submenuContainer) { - this.submenuDisposables = dispose(this.submenuDisposables); this.submenuContainer = undefined; } } } -class MenuSeparatorActionItem extends ActionItem { +class MenuSeparatorActionViewItem extends ActionViewItem { style(style: IMenuStyles): void { this.label.style.borderBottomColor = style.separatorColor ? `${style.separatorColor}` : null; } @@ -778,4 +805,4 @@ export function cleanMnemonic(label: string): string { const mnemonicInText = matches[0].charAt(0) === '&'; return label.replace(regex, mnemonicInText ? '$2' : '').trim(); -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/menu/menubar.ts b/src/vs/base/browser/ui/menu/menubar.ts index b5450749148..1ffcb47b9a1 100644 --- a/src/vs/base/browser/ui/menu/menubar.ts +++ b/src/vs/base/browser/ui/menu/menubar.ts @@ -14,19 +14,25 @@ import { cleanMnemonic, IMenuOptions, Menu, MENU_ESCAPED_MNEMONIC_REGEX, MENU_MN import { ActionRunner, IAction, IActionRunner } from 'vs/base/common/actions'; import { RunOnceScheduler } from 'vs/base/common/async'; import { Event, Emitter } from 'vs/base/common/event'; -import { KeyCode, KeyCodeUtils, ResolvedKeybinding } from 'vs/base/common/keyCodes'; -import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { KeyCode, ResolvedKeybinding, KeyMod } from 'vs/base/common/keyCodes'; +import { Disposable, dispose, IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { withNullAsUndefined } from 'vs/base/common/types'; +import { asArray } from 'vs/base/common/arrays'; +import { ScanCodeUtils, ScanCode } from 'vs/base/common/scanCode'; +import { isMacintosh } from 'vs/base/common/platform'; const $ = DOM.$; export interface IMenuBarOptions { enableMnemonics?: boolean; + disableAltFocus?: boolean; visibility?: string; - getKeybinding?: (action: IAction) => ResolvedKeybinding; + getKeybinding?: (action: IAction) => ResolvedKeybinding | undefined; + alwaysOnMnemonics?: boolean; } export interface MenuBarMenu { - actions: IAction[]; + actions: ReadonlyArray; label: string; } @@ -45,7 +51,7 @@ export class MenuBar extends Disposable { buttonElement: HTMLElement; titleElement: HTMLElement; label: string; - actions?: IAction[]; + actions?: ReadonlyArray; }[]; private overflowMenu: { @@ -69,14 +75,14 @@ export class MenuBar extends Disposable { private openedViaKeyboard: boolean; private awaitingAltRelease: boolean; private ignoreNextMouseUp: boolean; - private mnemonics: Map; + private mnemonics: Map; private updatePending: boolean; private _focusState: MenubarState; private actionRunner: IActionRunner; - private _onVisibilityChange: Emitter; - private _onFocusStateChange: Emitter; + private readonly _onVisibilityChange: Emitter; + private readonly _onFocusStateChange: Emitter; private numMenusShown: number; private menuStyle: IMenuStyles; @@ -85,10 +91,10 @@ export class MenuBar extends Disposable { constructor(private container: HTMLElement, private options: IMenuBarOptions = {}) { super(); - this.container.attributes['role'] = 'menubar'; + this.container.setAttribute('role', 'menubar'); this.menuCache = []; - this.mnemonics = new Map(); + this.mnemonics = new Map(); this._focusState = MenubarState.VISIBLE; @@ -109,21 +115,26 @@ export class MenuBar extends Disposable { this._register(DOM.addDisposableListener(this.container, DOM.EventType.KEY_DOWN, (e) => { let event = new StandardKeyboardEvent(e as KeyboardEvent); let eventHandled = true; - const key = !!e.key ? KeyCodeUtils.fromString(e.key) : KeyCode.Unknown; + const key = !!e.key ? e.key.toLocaleLowerCase() : ''; - if (event.equals(KeyCode.LeftArrow)) { + if (event.equals(KeyCode.LeftArrow) || (isMacintosh && event.equals(KeyCode.Tab | KeyMod.Shift))) { this.focusPrevious(); - } else if (event.equals(KeyCode.RightArrow)) { + } else if (event.equals(KeyCode.RightArrow) || (isMacintosh && event.equals(KeyCode.Tab))) { this.focusNext(); } else if (event.equals(KeyCode.Escape) && this.isFocused && !this.isOpen) { this.setUnfocusedState(); } else if (!this.isOpen && !event.ctrlKey && this.options.enableMnemonics && this.mnemonicsInUse && this.mnemonics.has(key)) { - const menuIndex = this.mnemonics.get(key); + const menuIndex = this.mnemonics.get(key)!; this.onMenuTriggered(menuIndex, false); } else { eventHandled = false; } + // Never allow default tab behavior + if (event.equals(KeyCode.Tab | KeyMod.Shift) || event.equals(KeyCode.Tab)) { + event.preventDefault(); + } + if (eventHandled) { event.preventDefault(); event.stopPropagation(); @@ -150,11 +161,14 @@ export class MenuBar extends Disposable { this._register(DOM.addDisposableListener(this.container, DOM.EventType.FOCUS_OUT, (e) => { let event = e as FocusEvent; - if (event.relatedTarget) { - if (!this.container.contains(event.relatedTarget as HTMLElement)) { - this.focusToReturn = undefined; - this.setUnfocusedState(); - } + // We are losing focus and there is no related target, e.g. webview case + if (!event.relatedTarget) { + this.setUnfocusedState(); + } + // We are losing focus and there is a target, reset focusToReturn value as not to redirect + else if (event.relatedTarget && !this.container.contains(event.relatedTarget as HTMLElement)) { + this.focusToReturn = undefined; + this.setUnfocusedState(); } })); @@ -163,7 +177,7 @@ export class MenuBar extends Disposable { return; } - const key = KeyCodeUtils.fromString(e.key); + const key = e.key.toLocaleLowerCase(); if (!this.mnemonics.has(key)) { return; } @@ -171,7 +185,7 @@ export class MenuBar extends Disposable { this.mnemonicsInUse = true; this.updateMnemonicVisibility(true); - const menuIndex = this.mnemonics.get(key); + const menuIndex = this.mnemonics.get(key)!; this.onMenuTriggered(menuIndex, false); })); @@ -179,7 +193,7 @@ export class MenuBar extends Disposable { } push(arg: MenuBarMenu | MenuBarMenu[]): void { - const menus: MenuBarMenu[] = !Array.isArray(arg) ? [arg] : arg; + const menus: MenuBarMenu[] = asArray(arg); menus.forEach((menuBarMenu) => { const menuIndex = this.menuCache.length; @@ -459,8 +473,8 @@ export class MenuBar extends Disposable { // Update the button label to reflect mnemonics titleElement.innerHTML = this.options.enableMnemonics ? - strings.escape(label).replace(MENU_ESCAPED_MNEMONIC_REGEX, '') : - cleanMenuLabel; + strings.escape(label).replace(MENU_ESCAPED_MNEMONIC_REGEX, '').replace(/&&/g, '&') : + cleanMenuLabel.replace(/&&/g, '&'); let mnemonicMatches = MENU_MNEMONIC_REGEX.exec(label); @@ -506,7 +520,7 @@ export class MenuBar extends Disposable { } private registerMnemonic(menuIndex: number, mnemonic: string): void { - this.mnemonics.set(KeyCodeUtils.fromString(mnemonic), menuIndex); + this.mnemonics.set(mnemonic.toLocaleLowerCase(), menuIndex); } private hideMenubar(): void { @@ -725,7 +739,7 @@ export class MenuBar extends Disposable { if (menuBarMenu.titleElement.children.length) { let child = menuBarMenu.titleElement.children.item(0) as HTMLElement; if (child) { - child.style.textDecoration = visible ? 'underline' : null; + child.style.textDecoration = (this.options.alwaysOnMnemonics || visible) ? 'underline' : null; } } }); @@ -770,6 +784,13 @@ export class MenuBar extends Disposable { return; } + // Prevent alt-key default if the menu is not hidden and we use alt to focus + if (modifierKeyStatus.event && !this.options.disableAltFocus) { + if (ScanCodeUtils.toEnum(modifierKeyStatus.event.code) === ScanCode.AltLeft) { + modifierKeyStatus.event.preventDefault(); + } + } + // Alt key pressed while menu is focused. This should return focus away from the menubar if (this.isFocused && modifierKeyStatus.lastKeyPressed === 'alt' && modifierKeyStatus.altKey) { this.setUnfocusedState(); @@ -780,7 +801,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) { + if (!this.isFocused && !(this.options.disableAltFocus && this.options.visibility !== 'toggle')) { this.mnemonicsInUse = true; this.focusedMenu = { index: this.numMenusShown > 0 ? 0 : MenuBar.OVERFLOW_INDEX }; this.focusState = MenubarState.FOCUSED; @@ -852,8 +873,8 @@ export class MenuBar extends Disposable { let menuOptions: IMenuOptions = { getKeyBinding: this.options.getKeybinding, actionRunner: this.actionRunner, - enableMnemonics: this.mnemonicsInUse && this.options.enableMnemonics, - ariaLabel: customMenu.buttonElement.attributes['aria-label'].value + enableMnemonics: this.options.alwaysOnMnemonics || (this.mnemonicsInUse && this.options.enableMnemonics), + ariaLabel: withNullAsUndefined(customMenu.buttonElement.getAttribute('aria-label')) }; let menuWidget = this._register(new Menu(menuHolder, customMenu.actions, menuOptions)); @@ -885,12 +906,13 @@ interface IModifierKeyStatus { ctrlKey: boolean; lastKeyPressed?: ModifierKey; lastKeyReleased?: ModifierKey; + event?: KeyboardEvent; } class ModifierKeyEmitter extends Emitter { - private _subscriptions: IDisposable[] = []; + private readonly _subscriptions = new DisposableStore(); private _keyStatus: IModifierKeyStatus; private static instance: ModifierKeyEmitter; @@ -903,7 +925,7 @@ class ModifierKeyEmitter extends Emitter { ctrlKey: false }; - this._subscriptions.push(domEvent(document.body, 'keydown', true)(e => { + this._subscriptions.add(domEvent(document.body, 'keydown', true)(e => { const event = new StandardKeyboardEvent(e); if (e.altKey && !this._keyStatus.altKey) { @@ -923,11 +945,12 @@ class ModifierKeyEmitter extends Emitter { this._keyStatus.shiftKey = e.shiftKey; if (this._keyStatus.lastKeyPressed) { + this._keyStatus.event = e; this.fire(this._keyStatus); } })); - this._subscriptions.push(domEvent(document.body, 'keyup', true)(e => { + this._subscriptions.add(domEvent(document.body, 'keyup', true)(e => { if (!e.altKey && this._keyStatus.altKey) { this._keyStatus.lastKeyReleased = 'alt'; } else if (!e.ctrlKey && this._keyStatus.ctrlKey) { @@ -947,15 +970,26 @@ class ModifierKeyEmitter extends Emitter { this._keyStatus.shiftKey = e.shiftKey; if (this._keyStatus.lastKeyReleased) { + this._keyStatus.event = e; this.fire(this._keyStatus); } })); - this._subscriptions.push(domEvent(document.body, 'mousedown', true)(e => { + this._subscriptions.add(domEvent(document.body, 'mousedown', true)(e => { this._keyStatus.lastKeyPressed = undefined; })); - this._subscriptions.push(domEvent(window, 'blur')(e => { + this._subscriptions.add(domEvent(document.body, 'mouseup', true)(e => { + this._keyStatus.lastKeyPressed = undefined; + })); + + this._subscriptions.add(domEvent(document.body, 'mousemove', true)(e => { + if (e.buttons) { + this._keyStatus.lastKeyPressed = undefined; + } + })); + + this._subscriptions.add(domEvent(window, 'blur')(e => { this._keyStatus.lastKeyPressed = undefined; this._keyStatus.lastKeyReleased = undefined; this._keyStatus.altKey = false; @@ -976,6 +1010,6 @@ class ModifierKeyEmitter extends Emitter { dispose() { super.dispose(); - this._subscriptions = dispose(this._subscriptions); + this._subscriptions.dispose(); } } \ No newline at end of file diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/README.md b/src/vs/base/browser/ui/octiconLabel/octicons/README.md deleted file mode 100644 index 10070733505..00000000000 --- a/src/vs/base/browser/ui/octiconLabel/octicons/README.md +++ /dev/null @@ -1 +0,0 @@ -If you intend to install Octicons locally, install `octicons-local.ttf`. It should appear as “github-octicons” in your font list. It is specially designed not to conflict with GitHub's web fonts. diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/cgmanifest.json b/src/vs/base/browser/ui/octiconLabel/octicons/cgmanifest.json deleted file mode 100644 index 3d13f99e346..00000000000 --- a/src/vs/base/browser/ui/octiconLabel/octicons/cgmanifest.json +++ /dev/null @@ -1,140 +0,0 @@ -{ - "registrations": [ - { - "component": { - "type": "other", - "other": { - "name": "octicons-code", - "version": "3.1.0", - "downloadUrl": "https://registry.npmjs.org/octicons/-/octicons-3.1.0.tgz" - } - }, - "licenseDetail": [ - "The MIT License (MIT)", - "", - "(c) 2012-2015 GitHub", - "", - "Permission is hereby granted, free of charge, to any person obtaining a copy", - "of this software and associated documentation files (the \"Software\"), to deal", - "in the Software without restriction, including without limitation the rights", - "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell", - "copies of the Software, and to permit persons to whom the Software is", - "furnished to do so, subject to the following conditions:", - "", - "The above copyright notice and this permission notice shall be included in", - "all copies or substantial portions of the Software.", - "", - "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR", - "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", - "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", - "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", - "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,", - "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN", - "THE SOFTWARE." - ], - "license": "MIT", - "version": "3.1.0" - }, - { - "component": { - "type": "other", - "other": { - "name": "octicons-font", - "version": "3.1.0", - "downloadUrl": "https://registry.npmjs.org/octicons/-/octicons-3.1.0.tgz" - } - }, - "licenseDetail": [ - "(c) 2012-2015 GitHub", - "", - "SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007", - "", - "PREAMBLE", - "The goals of the Open Font License (OFL) are to stimulate worldwide", - "development of collaborative font projects, to support the font creation", - "efforts of academic and linguistic communities, and to provide a free and", - "open framework in which fonts may be shared and improved in partnership", - "with others.", - "", - "The OFL allows the licensed fonts to be used, studied, modified and", - "redistributed freely as long as they are not sold by themselves. The", - "fonts, including any derivative works, can be bundled, embedded,", - "redistributed and/or sold with any software provided that any reserved", - "names are not used by derivative works. The fonts and derivatives,", - "however, cannot be released under any other type of license. The", - "requirement for fonts to remain under this license does not apply", - "to any document created using the fonts or their derivatives.", - "", - "DEFINITIONS", - "\"Font Software\" refers to the set of files released by the Copyright", - "Holder(s) under this license and clearly marked as such. This may", - "include source files, build scripts and documentation.", - "", - "\"Reserved Font Name\" refers to any names specified as such after the", - "copyright statement(s).", - "", - "\"Original Version\" refers to the collection of Font Software components as", - "distributed by the Copyright Holder(s).", - "", - "\"Modified Version\" refers to any derivative made by adding to, deleting,", - "or substituting -- in part or in whole -- any of the components of the", - "Original Version, by changing formats or by porting the Font Software to a", - "new environment.", - "", - "\"Author\" refers to any designer, engineer, programmer, technical", - "writer or other person who contributed to the Font Software.", - "", - "PERMISSION & CONDITIONS", - "Permission is hereby granted, free of charge, to any person obtaining", - "a copy of the Font Software, to use, study, copy, merge, embed, modify,", - "redistribute, and sell modified and unmodified copies of the Font", - "Software, subject to the following conditions:", - "", - "1) Neither the Font Software nor any of its individual components,", - "in Original or Modified Versions, may be sold by itself.", - "", - "2) Original or Modified Versions of the Font Software may be bundled,", - "redistributed and/or sold with any software, provided that each copy", - "contains the above copyright notice and this license. These can be", - "included either as stand-alone text files, human-readable headers or", - "in the appropriate machine-readable metadata fields within text or", - "binary files as long as those fields can be easily viewed by the user.", - "", - "3) No Modified Version of the Font Software may use the Reserved Font", - "Name(s) unless explicit written permission is granted by the corresponding", - "Copyright Holder. This restriction only applies to the primary font name as", - "presented to the users.", - "", - "4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font", - "Software shall not be used to promote, endorse or advertise any", - "Modified Version, except to acknowledge the contribution(s) of the", - "Copyright Holder(s) and the Author(s) or with their explicit written", - "permission.", - "", - "5) The Font Software, modified or unmodified, in part or in whole,", - "must be distributed entirely under this license, and must not be", - "distributed under any other license. The requirement for fonts to", - "remain under this license does not apply to any document created", - "using the Font Software.", - "", - "TERMINATION", - "This license becomes null and void if any of the above conditions are", - "not met.", - "", - "DISCLAIMER", - "THE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,", - "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF", - "MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT", - "OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE", - "COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,", - "INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL", - "DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING", - "FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM", - "OTHER DEALINGS IN THE FONT SOFTWARE." - ], - "license": "SIL OFL 1.1", - "version": "3.1.0" - } - ], - "version": 1 -} diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/octicons-local.ttf b/src/vs/base/browser/ui/octiconLabel/octicons/octicons-local.ttf deleted file mode 100644 index 2050d5e8abf..00000000000 Binary files a/src/vs/base/browser/ui/octiconLabel/octicons/octicons-local.ttf and /dev/null differ diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.css b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.css index 5a2a927f9a8..d9cc1b7a4fa 100644 --- a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.css +++ b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.css @@ -1,233 +1,248 @@ -/*! ***************************************************************************** -(c) 2012-2015 GitHub - -When using the GitHub logos, be sure to follow the GitHub logo guidelines (https://github.com/logos) - -Font License: SIL OFL 1.1 (http://scripts.sil.org/OFL) -Applies to all font files - -Code License: MIT (http://choosealicense.com/licenses/mit/) -Applies to all other files -***************************************************************************** */ - @font-face { - font-family: 'octicons'; - src: url('octicons.eot?#iefix') format('embedded-opentype'), - url('octicons.woff') format('woff'), - url('octicons.ttf') format('truetype'), - url('octicons.svg#octicons') format('svg'); - font-weight: normal; - font-style: normal; + font-family: "octicons"; + src: url("./octicons.ttf?1b0f2a9535896866c74dd24eedeb4374") format("truetype"), +url("./octicons.svg?1b0f2a9535896866c74dd24eedeb4374#octicons") format("svg"); } -/* - -.octicon is optimized for 16px. -.mega-octicon is optimized for 32px but can be used larger. - -*/ .octicon, .mega-octicon { - font: normal normal normal 16px/1 octicons; - display: inline-block; - text-decoration: none; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; + font: normal normal normal 16px/1 octicons; + display: inline-block; + text-decoration: none; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + .mega-octicon { font-size: 32px; } -.octicon-alert:before { content: '\f02d'} /*  */ -.octicon-arrow-down:before { content: '\f03f'} /*  */ -.octicon-arrow-left:before { content: '\f040'} /*  */ -.octicon-arrow-right:before { content: '\f03e'} /*  */ -.octicon-arrow-small-down:before { content: '\f0a0'} /*  */ -.octicon-arrow-small-left:before { content: '\f0a1'} /*  */ -.octicon-arrow-small-right:before { content: '\f071'} /*  */ -.octicon-arrow-small-up:before { content: '\f09f'} /*  */ -.octicon-arrow-up:before { content: '\f03d'} /*  */ -.octicon-microscope:before, -.octicon-beaker:before { content: '\f0dd'} /*  */ -.octicon-bell:before { content: '\f0de'} /*  */ -.octicon-book:before { content: '\f007'} /*  */ -.octicon-bookmark:before { content: '\f07b'} /*  */ -.octicon-briefcase:before { content: '\f0d3'} /*  */ -.octicon-broadcast:before { content: '\f048'} /*  */ -.octicon-browser:before { content: '\f0c5'} /*  */ -.octicon-bug:before { content: '\f091'} /*  */ -.octicon-calendar:before { content: '\f068'} /*  */ -.octicon-check:before { content: '\f03a'} /*  */ -.octicon-checklist:before { content: '\f076'} /*  */ -.octicon-chevron-down:before { content: '\f0a3'} /*  */ -.octicon-chevron-left:before { content: '\f0a4'} /*  */ -.octicon-chevron-right:before { content: '\f078'} /*  */ -.octicon-chevron-up:before { content: '\f0a2'} /*  */ -.octicon-circle-slash:before { content: '\f084'} /*  */ -.octicon-circuit-board:before { content: '\f0d6'} /*  */ -.octicon-clippy:before { content: '\f035'} /*  */ -.octicon-clock:before { content: '\f046'} /*  */ -.octicon-cloud-download:before { content: '\f00b'} /*  */ -.octicon-cloud-upload:before { content: '\f00c'} /*  */ -.octicon-code:before { content: '\f05f'} /*  */ -.octicon-color-mode:before { content: '\f065'} /*  */ -.octicon-comment-add:before, -.octicon-comment:before { content: '\f02b'} /*  */ -.octicon-comment-discussion:before { content: '\f04f'} /*  */ -.octicon-credit-card:before { content: '\f045'} /*  */ -.octicon-dash:before { content: '\f0ca'} /*  */ -.octicon-dashboard:before { content: '\f07d'} /*  */ -.octicon-database:before { content: '\f096'} /*  */ -.octicon-clone:before, -.octicon-desktop-download:before { content: '\f0dc'} /*  */ -.octicon-device-camera:before { content: '\f056'} /*  */ -.octicon-device-camera-video:before { content: '\f057'} /*  */ -.octicon-device-desktop:before { content: '\f27c'} /*  */ -.octicon-device-mobile:before { content: '\f038'} /*  */ -.octicon-diff:before { content: '\f04d'} /*  */ -.octicon-diff-added:before { content: '\f06b'} /*  */ -.octicon-diff-ignored:before { content: '\f099'} /*  */ -.octicon-diff-modified:before { content: '\f06d'} /*  */ -.octicon-diff-removed:before { content: '\f06c'} /*  */ -.octicon-diff-renamed:before { content: '\f06e'} /*  */ -.octicon-ellipsis:before { content: '\f09a'} /*  */ -.octicon-eye-unwatch:before, -.octicon-eye-watch:before, -.octicon-eye:before { content: '\f04e'} /*  */ -.octicon-file-binary:before { content: '\f094'} /*  */ -.octicon-file-code:before { content: '\f010'} /*  */ -.octicon-file-directory:before { content: '\f016'} /*  */ -.octicon-file-media:before { content: '\f012'} /*  */ -.octicon-file-pdf:before { content: '\f014'} /*  */ -.octicon-file-submodule:before { content: '\f017'} /*  */ -.octicon-file-symlink-directory:before { content: '\f0b1'} /*  */ -.octicon-file-symlink-file:before { content: '\f0b0'} /*  */ -.octicon-file-text:before { content: '\f011'} /*  */ -.octicon-file-zip:before { content: '\f013'} /*  */ -.octicon-flame:before { content: '\f0d2'} /*  */ -.octicon-fold:before { content: '\f0cc'} /*  */ -.octicon-gear:before { content: '\f02f'} /*  */ -.octicon-gift:before { content: '\f042'} /*  */ -.octicon-gist:before { content: '\f00e'} /*  */ -.octicon-gist-secret:before { content: '\f08c'} /*  */ -.octicon-git-branch-create:before, -.octicon-git-branch-delete:before, -.octicon-git-branch:before { content: '\f020'} /*  */ -.octicon-git-commit:before { content: '\f01f'} /*  */ -.octicon-git-compare:before { content: '\f0ac'} /*  */ -.octicon-git-merge:before { content: '\f023'} /*  */ -.octicon-git-pull-request-abandoned:before, -.octicon-git-pull-request:before { content: '\f009'} /*  */ -.octicon-globe:before { content: '\f0b6'} /*  */ -.octicon-graph:before { content: '\f043'} /*  */ -.octicon-heart:before { content: '\2665'} /* ♥ */ -.octicon-history:before { content: '\f07e'} /*  */ -.octicon-home:before { content: '\f08d'} /*  */ -.octicon-horizontal-rule:before { content: '\f070'} /*  */ -.octicon-hubot:before { content: '\f09d'} /*  */ -.octicon-inbox:before { content: '\f0cf'} /*  */ -.octicon-info:before { content: '\f059'} /*  */ -.octicon-issue-closed:before { content: '\f028'} /*  */ -.octicon-issue-opened:before { content: '\f026'} /*  */ -.octicon-issue-reopened:before { content: '\f027'} /*  */ -.octicon-jersey:before { content: '\f019'} /*  */ -.octicon-key:before { content: '\f049'} /*  */ -.octicon-keyboard:before { content: '\f00d'} /*  */ -.octicon-law:before { content: '\f0d8'} /*  */ -.octicon-light-bulb:before { content: '\f000'} /*  */ -.octicon-link:before { content: '\f05c'} /*  */ -.octicon-link-external:before { content: '\f07f'} /*  */ -.octicon-list-ordered:before { content: '\f062'} /*  */ -.octicon-list-unordered:before { content: '\f061'} /*  */ -.octicon-location:before { content: '\f060'} /*  */ -.octicon-gist-private:before, -.octicon-mirror-private:before, -.octicon-git-fork-private:before, -.octicon-lock:before { content: '\f06a'} /*  */ -.octicon-logo-github:before { content: '\f092'} /*  */ -.octicon-mail:before { content: '\f03b'} /*  */ -.octicon-mail-read:before { content: '\f03c'} /*  */ -.octicon-mail-reply:before { content: '\f051'} /*  */ -.octicon-mark-github:before { content: '\f00a'} /*  */ -.octicon-markdown:before { content: '\f0c9'} /*  */ -.octicon-megaphone:before { content: '\f077'} /*  */ -.octicon-mention:before { content: '\f0be'} /*  */ -.octicon-milestone:before { content: '\f075'} /*  */ -.octicon-mirror-public:before, -.octicon-mirror:before { content: '\f024'} /*  */ -.octicon-mortar-board:before { content: '\f0d7'} /*  */ -.octicon-mute:before { content: '\f080'} /*  */ -.octicon-no-newline:before { content: '\f09c'} /*  */ -.octicon-octoface:before { content: '\f008'} /*  */ -.octicon-organization:before { content: '\f037'} /*  */ -.octicon-package:before { content: '\f0c4'} /*  */ -.octicon-paintcan:before { content: '\f0d1'} /*  */ -.octicon-pencil:before { content: '\f058'} /*  */ -.octicon-person-add:before, -.octicon-person-follow:before, -.octicon-person:before { content: '\f018'} /*  */ -.octicon-pin:before { content: '\f041'} /*  */ -.octicon-plug:before { content: '\f0d4'} /*  */ -.octicon-repo-create:before, -.octicon-gist-new:before, -.octicon-file-directory-create:before, -.octicon-file-add:before, -.octicon-plus:before { content: '\f05d'} /*  */ -.octicon-primitive-dot:before { content: '\f052'} /*  */ -.octicon-primitive-square:before { content: '\f053'} /*  */ -.octicon-pulse:before { content: '\f085'} /*  */ -.octicon-question:before { content: '\f02c'} /*  */ -.octicon-quote:before { content: '\f063'} /*  */ -.octicon-radio-tower:before { content: '\f030'} /*  */ -.octicon-repo-delete:before, -.octicon-repo:before { content: '\f001'} /*  */ -.octicon-repo-clone:before { content: '\f04c'} /*  */ -.octicon-repo-force-push:before { content: '\f04a'} /*  */ -.octicon-gist-fork:before, -.octicon-repo-forked:before { content: '\f002'} /*  */ -.octicon-repo-pull:before { content: '\f006'} /*  */ -.octicon-repo-push:before { content: '\f005'} /*  */ -.octicon-rocket:before { content: '\f033'} /*  */ -.octicon-rss:before { content: '\f034'} /*  */ -.octicon-ruby:before { content: '\f047'} /*  */ -.octicon-screen-full:before { content: '\f066'} /*  */ -.octicon-screen-normal:before { content: '\f067'} /*  */ -.octicon-search-save:before, -.octicon-search:before { content: '\f02e'} /*  */ -.octicon-server:before { content: '\f097'} /*  */ -.octicon-settings:before { content: '\f07c'} /*  */ -.octicon-shield:before { content: '\f0e1'} /*  */ -.octicon-log-in:before, -.octicon-sign-in:before { content: '\f036'} /*  */ -.octicon-log-out:before, -.octicon-sign-out:before { content: '\f032'} /*  */ -.octicon-squirrel:before { content: '\f0b2'} /*  */ -.octicon-star-add:before, -.octicon-star-delete:before, -.octicon-star:before { content: '\f02a'} /*  */ -.octicon-stop:before { content: '\f08f'} /*  */ -.octicon-repo-sync:before, -.octicon-sync:before { content: '\f087'} /*  */ -.octicon-tag-remove:before, -.octicon-tag-add:before, -.octicon-tag:before { content: '\f015'} /*  */ -.octicon-telescope:before { content: '\f088'} /*  */ -.octicon-terminal:before { content: '\f0c8'} /*  */ -.octicon-three-bars:before { content: '\f05e'} /*  */ -.octicon-thumbsdown:before { content: '\f0db'} /*  */ -.octicon-thumbsup:before { content: '\f0da'} /*  */ -.octicon-tools:before { content: '\f031'} /*  */ -.octicon-trashcan:before { content: '\f0d0'} /*  */ -.octicon-triangle-down:before { content: '\f05b'} /*  */ -.octicon-triangle-left:before { content: '\f044'} /*  */ -.octicon-triangle-right:before { content: '\f05a'} /*  */ -.octicon-triangle-up:before { content: '\f0aa'} /*  */ -.octicon-unfold:before { content: '\f039'} /*  */ -.octicon-unmute:before { content: '\f0ba'} /*  */ -.octicon-versions:before { content: '\f064'} /*  */ -.octicon-watch:before { content: '\f0e0'} /*  */ -.octicon-remove-close:before, -.octicon-x:before { content: '\f081'} /*  */ -.octicon-zap:before { content: '\26A1'} /* ⚡ */ + + +.octicon-alert:before { content: "\f02d" } +.octicon-arrow-down:before { content: "\f03f" } +.octicon-arrow-left:before { content: "\f040" } +.octicon-arrow-right:before { content: "\f03e" } +.octicon-arrow-small-down:before { content: "\f0a0" } +.octicon-arrow-small-left:before { content: "\f0a1" } +.octicon-arrow-small-right:before { content: "\f071" } +.octicon-arrow-small-up:before { content: "\f09f" } +.octicon-arrow-up:before { content: "\f03d" } +.octicon-beaker:before { content: "\f0dd" } +.octicon-bell:before { content: "\f0de" } +.octicon-bold:before { content: "\f282" } +.octicon-book:before { content: "\f007" } +.octicon-bookmark:before { content: "\f07b" } +.octicon-briefcase:before { content: "\f0d3" } +.octicon-broadcast:before { content: "\f048" } +.octicon-browser:before { content: "\f0c5" } +.octicon-bug:before { content: "\f091" } +.octicon-calendar:before { content: "\f068" } +.octicon-check:before { content: "\f03a" } +.octicon-checklist:before { content: "\f076" } +.octicon-chevron-down:before { content: "\f0a3" } +.octicon-chevron-left:before { content: "\f0a4" } +.octicon-chevron-right:before { content: "\f078" } +.octicon-chevron-up:before { content: "\f0a2" } +.octicon-circle-slash:before { content: "\f084" } +.octicon-circuit-board:before { content: "\f0d6" } +.octicon-clippy:before { content: "\f035" } +.octicon-clock:before { content: "\f046" } +.octicon-clone:before { content: "\f0dc" } +.octicon-cloud-download:before { content: "\f00b" } +.octicon-cloud-upload:before { content: "\f00c" } +.octicon-code:before { content: "\f05f" } +.octicon-color-mode:before { content: "\f065" } +.octicon-comment-add:before { content: "\f02b" } +.octicon-comment-discussion:before { content: "\f04f" } +.octicon-comment:before { content: "\f02b" } +.octicon-credit-card:before { content: "\f045" } +.octicon-dash:before { content: "\f0ca" } +.octicon-dashboard:before { content: "\f07d" } +.octicon-database:before { content: "\f096" } +.octicon-desktop-download:before { content: "\f0dc" } +.octicon-device-camera-video:before { content: "\f057" } +.octicon-device-camera:before { content: "\f056" } +.octicon-device-desktop:before { content: "\f27c" } +.octicon-device-mobile:before { content: "\f038" } +.octicon-diff-added:before { content: "\f06b" } +.octicon-diff-ignored:before { content: "\f099" } +.octicon-diff-modified:before { content: "\f06d" } +.octicon-diff-removed:before { content: "\f06c" } +.octicon-diff-renamed:before { content: "\f06e" } +.octicon-diff:before { content: "\f04d" } +.octicon-ellipsis:before { content: "\f09a" } +.octicon-eye-unwatch:before { content: "\f04e" } +.octicon-eye-watch:before { content: "\f04e" } +.octicon-eye:before { content: "\f04e" } +.octicon-file-add:before { content: "\f05d" } +.octicon-file-binary:before { content: "\f094" } +.octicon-file-code:before { content: "\f010" } +.octicon-file-directory-create:before { content: "\f05d" } +.octicon-file-directory:before { content: "\f016" } +.octicon-file-media:before { content: "\f012" } +.octicon-file-pdf:before { content: "\f014" } +.octicon-file-submodule:before { content: "\f017" } +.octicon-file-symlink-directory:before { content: "\f0b1" } +.octicon-file-symlink-file:before { content: "\f0b0" } +.octicon-file-text:before { content: "\f283" } +.octicon-file-zip:before { content: "\f013" } +.octicon-file:before { content: "\f283" } +.octicon-flame:before { content: "\f0d2" } +.octicon-fold:before { content: "\f0cc" } +.octicon-gear:before { content: "\f02f" } +.octicon-gift:before { content: "\f042" } +.octicon-gist-fork:before { content: "\f002" } +.octicon-gist-new:before { content: "\f05d" } +.octicon-gist-private:before { content: "\f06a" } +.octicon-gist-secret:before { content: "\f08c" } +.octicon-gist:before { content: "\f00e" } +.octicon-git-branch-create:before { content: "\f020" } +.octicon-git-branch-delete:before { content: "\f020" } +.octicon-git-branch:before { content: "\f020" } +.octicon-git-commit:before { content: "\f01f" } +.octicon-git-compare:before { content: "\f0ac" } +.octicon-git-fork-private:before { content: "\f06a" } +.octicon-git-merge:before { content: "\f023" } +.octicon-git-pull-request-abandoned:before { content: "\f009" } +.octicon-git-pull-request:before { content: "\f009" } +.octicon-globe:before { content: "\f0b6" } +.octicon-grabber:before { content: "\f284" } +.octicon-graph:before { content: "\f043" } +.octicon-heart:before { content: "\2665" } +.octicon-history:before { content: "\f07e" } +.octicon-home:before { content: "\f08d" } +.octicon-horizontal-rule:before { content: "\f070" } +.octicon-hubot:before { content: "\f09d" } +.octicon-inbox:before { content: "\f0cf" } +.octicon-info:before { content: "\f059" } +.octicon-issue-closed:before { content: "\f028" } +.octicon-issue-opened:before { content: "\f026" } +.octicon-issue-reopened:before { content: "\f027" } +.octicon-italic:before { content: "\f285" } +.octicon-jersey:before { content: "\f019" } +.octicon-kebab-horizontal:before { content: "\f286" } +.octicon-kebab-vertical:before { content: "\f287" } +.octicon-key:before { content: "\f049" } +.octicon-keyboard:before { content: "\f00d" } +.octicon-law:before { content: "\f0d8" } +.octicon-light-bulb:before { content: "\f000" } +.octicon-link-external:before { content: "\f07f" } +.octicon-link:before { content: "\f05c" } +.octicon-list-ordered:before { content: "\f062" } +.octicon-list-unordered:before { content: "\f061" } +.octicon-location:before { content: "\f060" } +.octicon-lock:before { content: "\f06a" } +.octicon-log-in:before { content: "\f036" } +.octicon-log-out:before { content: "\f032" } +.octicon-logo-gist:before { content: "\f288" } +.octicon-logo-github:before { content: "\f092" } +.octicon-mail-read:before { content: "\f03c" } +.octicon-mail-reply:before { content: "\f28c" } +.octicon-mail:before { content: "\f03b" } +.octicon-mark-github:before { content: "\f00a" } +.octicon-markdown:before { content: "\f0c9" } +.octicon-megaphone:before { content: "\f077" } +.octicon-mention:before { content: "\f0be" } +.octicon-microscope:before { content: "\f0dd" } +.octicon-milestone:before { content: "\f075" } +.octicon-mirror-private:before { content: "\f06a" } +.octicon-mirror-public:before { content: "\f024" } +.octicon-mirror:before { content: "\f024" } +.octicon-mortar-board:before { content: "\f0d7" } +.octicon-mute:before { content: "\f080" } +.octicon-no-newline:before { content: "\f09c" } +.octicon-note:before { content: "\f289" } +.octicon-octoface:before { content: "\f008" } +.octicon-organization:before { content: "\f037" } +.octicon-organization-filled:before { content: "\26a2" } +.octicon-organization-outline:before { content: "\f037" } +.octicon-package:before { content: "\f0c4" } +.octicon-paintcan:before { content: "\f0d1" } +.octicon-pencil:before { content: "\f058" } +.octicon-person-add:before { content: "\f018" } +.octicon-person-follow:before { content: "\f018" } +.octicon-person:before { content: "\f018" } +.octicon-person-filled:before { content: "\26a3" } +.octicon-person-outline:before { content: "\f018" } +.octicon-pin:before { content: "\f041" } +.octicon-plug:before { content: "\f0d4" } +.octicon-plus-small:before { content: "\f28a" } +.octicon-plus:before { content: "\f05d" } +.octicon-primitive-dot:before { content: "\f052" } +.octicon-primitive-square:before { content: "\f053" } +.octicon-project:before { content: "\f28b" } +.octicon-pulse:before { content: "\f085" } +.octicon-question:before { content: "\f02c" } +.octicon-quote:before { content: "\f063" } +.octicon-radio-tower:before { content: "\f030" } +.octicon-remove-close:before { content: "\f081" } +.octicon-reply:before { content: "\f28c" } +.octicon-repo-clone:before { content: "\f04c" } +.octicon-repo-create:before { content: "\f05d" } +.octicon-repo-delete:before { content: "\f001" } +.octicon-repo-force-push:before { content: "\f04a" } +.octicon-repo-forked:before { content: "\f002" } +.octicon-repo-pull:before { content: "\f006" } +.octicon-repo-push:before { content: "\f005" } +.octicon-repo-sync:before { content: "\f087" } +.octicon-repo:before { content: "\f001" } +.octicon-report:before { content: "\f28d" } +.octicon-rocket:before { content: "\f033" } +.octicon-rss:before { content: "\f034" } +.octicon-ruby:before { content: "\f047" } +.octicon-screen-full:before { content: "\f066" } +.octicon-screen-normal:before { content: "\f067" } +.octicon-search-save:before { content: "\f02e" } +.octicon-search:before { content: "\f02e" } +.octicon-server:before { content: "\f097" } +.octicon-settings:before { content: "\f07c" } +.octicon-shield:before { content: "\f0e1" } +.octicon-sign-in:before { content: "\f036" } +.octicon-sign-out:before { content: "\f032" } +.octicon-smiley:before { content: "\f27d" } +.octicon-squirrel:before { content: "\f0b2" } +.octicon-star-add:before { content: "\f02a" } +.octicon-star-delete:before { content: "\f02a" } +.octicon-star:before { content: "\f02a" } +.octicon-stop:before { content: "\f08f" } +.octicon-sync:before { content: "\f087" } +.octicon-tag-add:before { content: "\f015" } +.octicon-tag-remove:before { content: "\f015" } +.octicon-tag:before { content: "\f015" } +.octicon-tasklist:before { content: "\f27e" } +.octicon-telescope:before { content: "\f088" } +.octicon-terminal:before { content: "\f0c8" } +.octicon-text-size:before { content: "\f27f" } +.octicon-three-bars:before { content: "\f05e" } +.octicon-thumbsdown:before { content: "\f0db" } +.octicon-thumbsup:before { content: "\f0da" } +.octicon-tools:before { content: "\f031" } +.octicon-trashcan:before { content: "\f0d0" } +.octicon-triangle-down:before { content: "\f05b" } +.octicon-triangle-left:before { content: "\f044" } +.octicon-triangle-right:before { content: "\f05a" } +.octicon-triangle-up:before { content: "\f0aa" } +.octicon-unfold:before { content: "\f039" } +.octicon-unmute:before { content: "\f0ba" } +.octicon-unverified:before { content: "\f280" } +.octicon-verified:before { content: "\f281" } +.octicon-versions:before { content: "\f064" } +.octicon-watch:before { content: "\f0e0" } +.octicon-x:before { content: "\f081" } +.octicon-zap:before { content: "\26a1" } +.octicon-archive:before { content: "\f101" } +.octicon-arrow-both:before { content: "\f102" } +.octicon-error:before { content: "\f103" } +.octicon-eye-closed:before { content: "\f104" } +.octicon-fold-down:before { content: "\f105" } +.octicon-fold-up:before { content: "\f106" } +.octicon-github-action:before { content: "\f107" } +.octicon-info-outline:before { content: "\f108" } +.octicon-play:before { content: "\f109" } +.octicon-remote:before { content: "\f10a" } +.octicon-request-changes:before { content: "\f10b" } +.octicon-smiley-outline:before { content: "\f10c" } +.octicon-warning:before { content: "\f10d" } diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.eot b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.eot deleted file mode 100644 index 2bf20bca003..00000000000 Binary files a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.eot and /dev/null differ diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.less b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.less deleted file mode 100644 index d1d751ea45e..00000000000 --- a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.less +++ /dev/null @@ -1,220 +0,0 @@ -@octicons-font-path: "."; -@octicons-version: "396334ee3da78f4302d25c758ae3e3ce5dc3c97d"; - -@font-face { - font-family: 'octicons'; - src: ~"url('@{octicons-font-path}/octicons.eot?#iefix&v=@{octicons-version}') format('embedded-opentype')", - ~"url('@{octicons-font-path}/octicons.woff?v=@{octicons-version}') format('woff')", - ~"url('@{octicons-font-path}/octicons.ttf?v=@{octicons-version}') format('truetype')", - ~"url('@{octicons-font-path}/octicons.svg?v=@{octicons-version}#octicons') format('svg')"; - font-weight: normal; - font-style: normal; -} - -// .octicon is optimized for 16px. -// .mega-octicon is optimized for 32px but can be used larger. -.octicon, .mega-octicon { - font: normal normal normal 16px/1 octicons; - display: inline-block; - text-decoration: none; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.mega-octicon { font-size: 32px; } - -.octicon-alert:before { content: '\f02d'} /*  */ -.octicon-arrow-down:before { content: '\f03f'} /*  */ -.octicon-arrow-left:before { content: '\f040'} /*  */ -.octicon-arrow-right:before { content: '\f03e'} /*  */ -.octicon-arrow-small-down:before { content: '\f0a0'} /*  */ -.octicon-arrow-small-left:before { content: '\f0a1'} /*  */ -.octicon-arrow-small-right:before { content: '\f071'} /*  */ -.octicon-arrow-small-up:before { content: '\f09f'} /*  */ -.octicon-arrow-up:before { content: '\f03d'} /*  */ -.octicon-microscope:before, -.octicon-beaker:before { content: '\f0dd'} /*  */ -.octicon-bell:before { content: '\f0de'} /*  */ -.octicon-book:before { content: '\f007'} /*  */ -.octicon-bookmark:before { content: '\f07b'} /*  */ -.octicon-briefcase:before { content: '\f0d3'} /*  */ -.octicon-broadcast:before { content: '\f048'} /*  */ -.octicon-browser:before { content: '\f0c5'} /*  */ -.octicon-bug:before { content: '\f091'} /*  */ -.octicon-calendar:before { content: '\f068'} /*  */ -.octicon-check:before { content: '\f03a'} /*  */ -.octicon-checklist:before { content: '\f076'} /*  */ -.octicon-chevron-down:before { content: '\f0a3'} /*  */ -.octicon-chevron-left:before { content: '\f0a4'} /*  */ -.octicon-chevron-right:before { content: '\f078'} /*  */ -.octicon-chevron-up:before { content: '\f0a2'} /*  */ -.octicon-circle-slash:before { content: '\f084'} /*  */ -.octicon-circuit-board:before { content: '\f0d6'} /*  */ -.octicon-clippy:before { content: '\f035'} /*  */ -.octicon-clock:before { content: '\f046'} /*  */ -.octicon-cloud-download:before { content: '\f00b'} /*  */ -.octicon-cloud-upload:before { content: '\f00c'} /*  */ -.octicon-code:before { content: '\f05f'} /*  */ -.octicon-color-mode:before { content: '\f065'} /*  */ -.octicon-comment-add:before, -.octicon-comment:before { content: '\f02b'} /*  */ -.octicon-comment-discussion:before { content: '\f04f'} /*  */ -.octicon-credit-card:before { content: '\f045'} /*  */ -.octicon-dash:before { content: '\f0ca'} /*  */ -.octicon-dashboard:before { content: '\f07d'} /*  */ -.octicon-database:before { content: '\f096'} /*  */ -.octicon-clone:before, -.octicon-desktop-download:before { content: '\f0dc'} /*  */ -.octicon-device-camera:before { content: '\f056'} /*  */ -.octicon-device-camera-video:before { content: '\f057'} /*  */ -.octicon-device-desktop:before { content: '\f27c'} /*  */ -.octicon-device-mobile:before { content: '\f038'} /*  */ -.octicon-diff:before { content: '\f04d'} /*  */ -.octicon-diff-added:before { content: '\f06b'} /*  */ -.octicon-diff-ignored:before { content: '\f099'} /*  */ -.octicon-diff-modified:before { content: '\f06d'} /*  */ -.octicon-diff-removed:before { content: '\f06c'} /*  */ -.octicon-diff-renamed:before { content: '\f06e'} /*  */ -.octicon-ellipsis:before { content: '\f09a'} /*  */ -.octicon-eye-unwatch:before, -.octicon-eye-watch:before, -.octicon-eye:before { content: '\f04e'} /*  */ -.octicon-file-binary:before { content: '\f094'} /*  */ -.octicon-file-code:before { content: '\f010'} /*  */ -.octicon-file-directory:before { content: '\f016'} /*  */ -.octicon-file-media:before { content: '\f012'} /*  */ -.octicon-file-pdf:before { content: '\f014'} /*  */ -.octicon-file-submodule:before { content: '\f017'} /*  */ -.octicon-file-symlink-directory:before { content: '\f0b1'} /*  */ -.octicon-file-symlink-file:before { content: '\f0b0'} /*  */ -.octicon-file-text:before { content: '\f011'} /*  */ -.octicon-file-zip:before { content: '\f013'} /*  */ -.octicon-flame:before { content: '\f0d2'} /*  */ -.octicon-fold:before { content: '\f0cc'} /*  */ -.octicon-gear:before { content: '\f02f'} /*  */ -.octicon-gift:before { content: '\f042'} /*  */ -.octicon-gist:before { content: '\f00e'} /*  */ -.octicon-gist-secret:before { content: '\f08c'} /*  */ -.octicon-git-branch-create:before, -.octicon-git-branch-delete:before, -.octicon-git-branch:before { content: '\f020'} /*  */ -.octicon-git-commit:before { content: '\f01f'} /*  */ -.octicon-git-compare:before { content: '\f0ac'} /*  */ -.octicon-git-merge:before { content: '\f023'} /*  */ -.octicon-git-pull-request-abandoned:before, -.octicon-git-pull-request:before { content: '\f009'} /*  */ -.octicon-globe:before { content: '\f0b6'} /*  */ -.octicon-graph:before { content: '\f043'} /*  */ -.octicon-heart:before { content: '\2665'} /* ♥ */ -.octicon-history:before { content: '\f07e'} /*  */ -.octicon-home:before { content: '\f08d'} /*  */ -.octicon-horizontal-rule:before { content: '\f070'} /*  */ -.octicon-hubot:before { content: '\f09d'} /*  */ -.octicon-inbox:before { content: '\f0cf'} /*  */ -.octicon-info:before { content: '\f059'} /*  */ -.octicon-issue-closed:before { content: '\f028'} /*  */ -.octicon-issue-opened:before { content: '\f026'} /*  */ -.octicon-issue-reopened:before { content: '\f027'} /*  */ -.octicon-jersey:before { content: '\f019'} /*  */ -.octicon-key:before { content: '\f049'} /*  */ -.octicon-keyboard:before { content: '\f00d'} /*  */ -.octicon-law:before { content: '\f0d8'} /*  */ -.octicon-light-bulb:before { content: '\f000'} /*  */ -.octicon-link:before { content: '\f05c'} /*  */ -.octicon-link-external:before { content: '\f07f'} /*  */ -.octicon-list-ordered:before { content: '\f062'} /*  */ -.octicon-list-unordered:before { content: '\f061'} /*  */ -.octicon-location:before { content: '\f060'} /*  */ -.octicon-gist-private:before, -.octicon-mirror-private:before, -.octicon-git-fork-private:before, -.octicon-lock:before { content: '\f06a'} /*  */ -.octicon-logo-github:before { content: '\f092'} /*  */ -.octicon-mail:before { content: '\f03b'} /*  */ -.octicon-mail-read:before { content: '\f03c'} /*  */ -.octicon-mail-reply:before { content: '\f051'} /*  */ -.octicon-mark-github:before { content: '\f00a'} /*  */ -.octicon-markdown:before { content: '\f0c9'} /*  */ -.octicon-megaphone:before { content: '\f077'} /*  */ -.octicon-mention:before { content: '\f0be'} /*  */ -.octicon-milestone:before { content: '\f075'} /*  */ -.octicon-mirror-public:before, -.octicon-mirror:before { content: '\f024'} /*  */ -.octicon-mortar-board:before { content: '\f0d7'} /*  */ -.octicon-mute:before { content: '\f080'} /*  */ -.octicon-no-newline:before { content: '\f09c'} /*  */ -.octicon-octoface:before { content: '\f008'} /*  */ -.octicon-organization:before { content: '\f037'} /*  */ -.octicon-package:before { content: '\f0c4'} /*  */ -.octicon-paintcan:before { content: '\f0d1'} /*  */ -.octicon-pencil:before { content: '\f058'} /*  */ -.octicon-person-add:before, -.octicon-person-follow:before, -.octicon-person:before { content: '\f018'} /*  */ -.octicon-pin:before { content: '\f041'} /*  */ -.octicon-plug:before { content: '\f0d4'} /*  */ -.octicon-repo-create:before, -.octicon-gist-new:before, -.octicon-file-directory-create:before, -.octicon-file-add:before, -.octicon-plus:before { content: '\f05d'} /*  */ -.octicon-primitive-dot:before { content: '\f052'} /*  */ -.octicon-primitive-square:before { content: '\f053'} /*  */ -.octicon-pulse:before { content: '\f085'} /*  */ -.octicon-question:before { content: '\f02c'} /*  */ -.octicon-quote:before { content: '\f063'} /*  */ -.octicon-radio-tower:before { content: '\f030'} /*  */ -.octicon-repo-delete:before, -.octicon-repo:before { content: '\f001'} /*  */ -.octicon-repo-clone:before { content: '\f04c'} /*  */ -.octicon-repo-force-push:before { content: '\f04a'} /*  */ -.octicon-gist-fork:before, -.octicon-repo-forked:before { content: '\f002'} /*  */ -.octicon-repo-pull:before { content: '\f006'} /*  */ -.octicon-repo-push:before { content: '\f005'} /*  */ -.octicon-rocket:before { content: '\f033'} /*  */ -.octicon-rss:before { content: '\f034'} /*  */ -.octicon-ruby:before { content: '\f047'} /*  */ -.octicon-screen-full:before { content: '\f066'} /*  */ -.octicon-screen-normal:before { content: '\f067'} /*  */ -.octicon-search-save:before, -.octicon-search:before { content: '\f02e'} /*  */ -.octicon-server:before { content: '\f097'} /*  */ -.octicon-settings:before { content: '\f07c'} /*  */ -.octicon-shield:before { content: '\f0e1'} /*  */ -.octicon-log-in:before, -.octicon-sign-in:before { content: '\f036'} /*  */ -.octicon-log-out:before, -.octicon-sign-out:before { content: '\f032'} /*  */ -.octicon-squirrel:before { content: '\f0b2'} /*  */ -.octicon-star-add:before, -.octicon-star-delete:before, -.octicon-star:before { content: '\f02a'} /*  */ -.octicon-stop:before { content: '\f08f'} /*  */ -.octicon-repo-sync:before, -.octicon-sync:before { content: '\f087'} /*  */ -.octicon-tag-remove:before, -.octicon-tag-add:before, -.octicon-tag:before { content: '\f015'} /*  */ -.octicon-telescope:before { content: '\f088'} /*  */ -.octicon-terminal:before { content: '\f0c8'} /*  */ -.octicon-three-bars:before { content: '\f05e'} /*  */ -.octicon-thumbsdown:before { content: '\f0db'} /*  */ -.octicon-thumbsup:before { content: '\f0da'} /*  */ -.octicon-tools:before { content: '\f031'} /*  */ -.octicon-trashcan:before { content: '\f0d0'} /*  */ -.octicon-triangle-down:before { content: '\f05b'} /*  */ -.octicon-triangle-left:before { content: '\f044'} /*  */ -.octicon-triangle-right:before { content: '\f05a'} /*  */ -.octicon-triangle-up:before { content: '\f0aa'} /*  */ -.octicon-unfold:before { content: '\f039'} /*  */ -.octicon-unmute:before { content: '\f0ba'} /*  */ -.octicon-versions:before { content: '\f064'} /*  */ -.octicon-watch:before { content: '\f0e0'} /*  */ -.octicon-remove-close:before, -.octicon-x:before { content: '\f081'} /*  */ -.octicon-zap:before { content: '\26A1'} /* ⚡ */ diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.scss b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.scss deleted file mode 100644 index 0902cedce8f..00000000000 --- a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.scss +++ /dev/null @@ -1,220 +0,0 @@ -$octicons-font-path: "." !default; -$octicons-version: "396334ee3da78f4302d25c758ae3e3ce5dc3c97d"; - -@font-face { - font-family: 'octicons'; - src: url('#{$octicons-font-path}/octicons.eot?#iefix&v=#{$octicons-version}') format('embedded-opentype'), - url('#{$octicons-font-path}/octicons.woff?v=#{$octicons-version}') format('woff'), - url('#{$octicons-font-path}/octicons.ttf?v=#{$octicons-version}') format('truetype'), - url('#{$octicons-font-path}/octicons.svg?v=#{$octicons-version}#octicons') format('svg'); - font-weight: normal; - font-style: normal; -} - -// .octicon is optimized for 16px. -// .mega-octicon is optimized for 32px but can be used larger. -.octicon, .mega-octicon { - font: normal normal normal 16px/1 octicons; - display: inline-block; - text-decoration: none; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.mega-octicon { font-size: 32px; } - -.octicon-alert:before { content: '\f02d'} /*  */ -.octicon-arrow-down:before { content: '\f03f'} /*  */ -.octicon-arrow-left:before { content: '\f040'} /*  */ -.octicon-arrow-right:before { content: '\f03e'} /*  */ -.octicon-arrow-small-down:before { content: '\f0a0'} /*  */ -.octicon-arrow-small-left:before { content: '\f0a1'} /*  */ -.octicon-arrow-small-right:before { content: '\f071'} /*  */ -.octicon-arrow-small-up:before { content: '\f09f'} /*  */ -.octicon-arrow-up:before { content: '\f03d'} /*  */ -.octicon-microscope:before, -.octicon-beaker:before { content: '\f0dd'} /*  */ -.octicon-bell:before { content: '\f0de'} /*  */ -.octicon-book:before { content: '\f007'} /*  */ -.octicon-bookmark:before { content: '\f07b'} /*  */ -.octicon-briefcase:before { content: '\f0d3'} /*  */ -.octicon-broadcast:before { content: '\f048'} /*  */ -.octicon-browser:before { content: '\f0c5'} /*  */ -.octicon-bug:before { content: '\f091'} /*  */ -.octicon-calendar:before { content: '\f068'} /*  */ -.octicon-check:before { content: '\f03a'} /*  */ -.octicon-checklist:before { content: '\f076'} /*  */ -.octicon-chevron-down:before { content: '\f0a3'} /*  */ -.octicon-chevron-left:before { content: '\f0a4'} /*  */ -.octicon-chevron-right:before { content: '\f078'} /*  */ -.octicon-chevron-up:before { content: '\f0a2'} /*  */ -.octicon-circle-slash:before { content: '\f084'} /*  */ -.octicon-circuit-board:before { content: '\f0d6'} /*  */ -.octicon-clippy:before { content: '\f035'} /*  */ -.octicon-clock:before { content: '\f046'} /*  */ -.octicon-cloud-download:before { content: '\f00b'} /*  */ -.octicon-cloud-upload:before { content: '\f00c'} /*  */ -.octicon-code:before { content: '\f05f'} /*  */ -.octicon-color-mode:before { content: '\f065'} /*  */ -.octicon-comment-add:before, -.octicon-comment:before { content: '\f02b'} /*  */ -.octicon-comment-discussion:before { content: '\f04f'} /*  */ -.octicon-credit-card:before { content: '\f045'} /*  */ -.octicon-dash:before { content: '\f0ca'} /*  */ -.octicon-dashboard:before { content: '\f07d'} /*  */ -.octicon-database:before { content: '\f096'} /*  */ -.octicon-clone:before, -.octicon-desktop-download:before { content: '\f0dc'} /*  */ -.octicon-device-camera:before { content: '\f056'} /*  */ -.octicon-device-camera-video:before { content: '\f057'} /*  */ -.octicon-device-desktop:before { content: '\f27c'} /*  */ -.octicon-device-mobile:before { content: '\f038'} /*  */ -.octicon-diff:before { content: '\f04d'} /*  */ -.octicon-diff-added:before { content: '\f06b'} /*  */ -.octicon-diff-ignored:before { content: '\f099'} /*  */ -.octicon-diff-modified:before { content: '\f06d'} /*  */ -.octicon-diff-removed:before { content: '\f06c'} /*  */ -.octicon-diff-renamed:before { content: '\f06e'} /*  */ -.octicon-ellipsis:before { content: '\f09a'} /*  */ -.octicon-eye-unwatch:before, -.octicon-eye-watch:before, -.octicon-eye:before { content: '\f04e'} /*  */ -.octicon-file-binary:before { content: '\f094'} /*  */ -.octicon-file-code:before { content: '\f010'} /*  */ -.octicon-file-directory:before { content: '\f016'} /*  */ -.octicon-file-media:before { content: '\f012'} /*  */ -.octicon-file-pdf:before { content: '\f014'} /*  */ -.octicon-file-submodule:before { content: '\f017'} /*  */ -.octicon-file-symlink-directory:before { content: '\f0b1'} /*  */ -.octicon-file-symlink-file:before { content: '\f0b0'} /*  */ -.octicon-file-text:before { content: '\f011'} /*  */ -.octicon-file-zip:before { content: '\f013'} /*  */ -.octicon-flame:before { content: '\f0d2'} /*  */ -.octicon-fold:before { content: '\f0cc'} /*  */ -.octicon-gear:before { content: '\f02f'} /*  */ -.octicon-gift:before { content: '\f042'} /*  */ -.octicon-gist:before { content: '\f00e'} /*  */ -.octicon-gist-secret:before { content: '\f08c'} /*  */ -.octicon-git-branch-create:before, -.octicon-git-branch-delete:before, -.octicon-git-branch:before { content: '\f020'} /*  */ -.octicon-git-commit:before { content: '\f01f'} /*  */ -.octicon-git-compare:before { content: '\f0ac'} /*  */ -.octicon-git-merge:before { content: '\f023'} /*  */ -.octicon-git-pull-request-abandoned:before, -.octicon-git-pull-request:before { content: '\f009'} /*  */ -.octicon-globe:before { content: '\f0b6'} /*  */ -.octicon-graph:before { content: '\f043'} /*  */ -.octicon-heart:before { content: '\2665'} /* ♥ */ -.octicon-history:before { content: '\f07e'} /*  */ -.octicon-home:before { content: '\f08d'} /*  */ -.octicon-horizontal-rule:before { content: '\f070'} /*  */ -.octicon-hubot:before { content: '\f09d'} /*  */ -.octicon-inbox:before { content: '\f0cf'} /*  */ -.octicon-info:before { content: '\f059'} /*  */ -.octicon-issue-closed:before { content: '\f028'} /*  */ -.octicon-issue-opened:before { content: '\f026'} /*  */ -.octicon-issue-reopened:before { content: '\f027'} /*  */ -.octicon-jersey:before { content: '\f019'} /*  */ -.octicon-key:before { content: '\f049'} /*  */ -.octicon-keyboard:before { content: '\f00d'} /*  */ -.octicon-law:before { content: '\f0d8'} /*  */ -.octicon-light-bulb:before { content: '\f000'} /*  */ -.octicon-link:before { content: '\f05c'} /*  */ -.octicon-link-external:before { content: '\f07f'} /*  */ -.octicon-list-ordered:before { content: '\f062'} /*  */ -.octicon-list-unordered:before { content: '\f061'} /*  */ -.octicon-location:before { content: '\f060'} /*  */ -.octicon-gist-private:before, -.octicon-mirror-private:before, -.octicon-git-fork-private:before, -.octicon-lock:before { content: '\f06a'} /*  */ -.octicon-logo-github:before { content: '\f092'} /*  */ -.octicon-mail:before { content: '\f03b'} /*  */ -.octicon-mail-read:before { content: '\f03c'} /*  */ -.octicon-mail-reply:before { content: '\f051'} /*  */ -.octicon-mark-github:before { content: '\f00a'} /*  */ -.octicon-markdown:before { content: '\f0c9'} /*  */ -.octicon-megaphone:before { content: '\f077'} /*  */ -.octicon-mention:before { content: '\f0be'} /*  */ -.octicon-milestone:before { content: '\f075'} /*  */ -.octicon-mirror-public:before, -.octicon-mirror:before { content: '\f024'} /*  */ -.octicon-mortar-board:before { content: '\f0d7'} /*  */ -.octicon-mute:before { content: '\f080'} /*  */ -.octicon-no-newline:before { content: '\f09c'} /*  */ -.octicon-octoface:before { content: '\f008'} /*  */ -.octicon-organization:before { content: '\f037'} /*  */ -.octicon-package:before { content: '\f0c4'} /*  */ -.octicon-paintcan:before { content: '\f0d1'} /*  */ -.octicon-pencil:before { content: '\f058'} /*  */ -.octicon-person-add:before, -.octicon-person-follow:before, -.octicon-person:before { content: '\f018'} /*  */ -.octicon-pin:before { content: '\f041'} /*  */ -.octicon-plug:before { content: '\f0d4'} /*  */ -.octicon-repo-create:before, -.octicon-gist-new:before, -.octicon-file-directory-create:before, -.octicon-file-add:before, -.octicon-plus:before { content: '\f05d'} /*  */ -.octicon-primitive-dot:before { content: '\f052'} /*  */ -.octicon-primitive-square:before { content: '\f053'} /*  */ -.octicon-pulse:before { content: '\f085'} /*  */ -.octicon-question:before { content: '\f02c'} /*  */ -.octicon-quote:before { content: '\f063'} /*  */ -.octicon-radio-tower:before { content: '\f030'} /*  */ -.octicon-repo-delete:before, -.octicon-repo:before { content: '\f001'} /*  */ -.octicon-repo-clone:before { content: '\f04c'} /*  */ -.octicon-repo-force-push:before { content: '\f04a'} /*  */ -.octicon-gist-fork:before, -.octicon-repo-forked:before { content: '\f002'} /*  */ -.octicon-repo-pull:before { content: '\f006'} /*  */ -.octicon-repo-push:before { content: '\f005'} /*  */ -.octicon-rocket:before { content: '\f033'} /*  */ -.octicon-rss:before { content: '\f034'} /*  */ -.octicon-ruby:before { content: '\f047'} /*  */ -.octicon-screen-full:before { content: '\f066'} /*  */ -.octicon-screen-normal:before { content: '\f067'} /*  */ -.octicon-search-save:before, -.octicon-search:before { content: '\f02e'} /*  */ -.octicon-server:before { content: '\f097'} /*  */ -.octicon-settings:before { content: '\f07c'} /*  */ -.octicon-shield:before { content: '\f0e1'} /*  */ -.octicon-log-in:before, -.octicon-sign-in:before { content: '\f036'} /*  */ -.octicon-log-out:before, -.octicon-sign-out:before { content: '\f032'} /*  */ -.octicon-squirrel:before { content: '\f0b2'} /*  */ -.octicon-star-add:before, -.octicon-star-delete:before, -.octicon-star:before { content: '\f02a'} /*  */ -.octicon-stop:before { content: '\f08f'} /*  */ -.octicon-repo-sync:before, -.octicon-sync:before { content: '\f087'} /*  */ -.octicon-tag-remove:before, -.octicon-tag-add:before, -.octicon-tag:before { content: '\f015'} /*  */ -.octicon-telescope:before { content: '\f088'} /*  */ -.octicon-terminal:before { content: '\f0c8'} /*  */ -.octicon-three-bars:before { content: '\f05e'} /*  */ -.octicon-thumbsdown:before { content: '\f0db'} /*  */ -.octicon-thumbsup:before { content: '\f0da'} /*  */ -.octicon-tools:before { content: '\f031'} /*  */ -.octicon-trashcan:before { content: '\f0d0'} /*  */ -.octicon-triangle-down:before { content: '\f05b'} /*  */ -.octicon-triangle-left:before { content: '\f044'} /*  */ -.octicon-triangle-right:before { content: '\f05a'} /*  */ -.octicon-triangle-up:before { content: '\f0aa'} /*  */ -.octicon-unfold:before { content: '\f039'} /*  */ -.octicon-unmute:before { content: '\f0ba'} /*  */ -.octicon-versions:before { content: '\f064'} /*  */ -.octicon-watch:before { content: '\f0e0'} /*  */ -.octicon-remove-close:before, -.octicon-x:before { content: '\f081'} /*  */ -.octicon-zap:before { content: '\26A1'} /* ⚡ */ diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.svg b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.svg index d932988bb57..3f4ab4f1807 100644 --- a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.svg +++ b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.svg @@ -1,183 +1,582 @@ - - + + - -(c) 2012-2015 GitHub - -When using the GitHub logos, be sure to follow the GitHub logo guidelines (https://github.com/logos) - -Font License: SIL OFL 1.1 (http://scripts.sil.org/OFL) -Applies to all font files - -Code License: MIT (http://choosealicense.com/licenses/mit/) -Applies to all other files - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.ttf b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.ttf index 32e6720a733..4eb17f9045c 100644 Binary files a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.ttf and b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.ttf differ diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.woff b/src/vs/base/browser/ui/octiconLabel/octicons/octicons.woff deleted file mode 100644 index cbf9f62ea65..00000000000 Binary files a/src/vs/base/browser/ui/octiconLabel/octicons/octicons.woff and /dev/null differ diff --git a/src/vs/base/browser/ui/octiconLabel/octicons/sprockets-octicons.scss b/src/vs/base/browser/ui/octiconLabel/octicons/sprockets-octicons.scss deleted file mode 100644 index cef21ae62ee..00000000000 --- a/src/vs/base/browser/ui/octiconLabel/octicons/sprockets-octicons.scss +++ /dev/null @@ -1,217 +0,0 @@ -@font-face { - font-family: 'octicons'; - src: font-url('octicons.eot?#iefix') format('embedded-opentype'), - font-url('octicons.woff') format('woff'), - font-url('octicons.ttf') format('truetype'), - font-url('octicons.svg#octicons') format('svg'); - font-weight: normal; - font-style: normal; -} - -// .octicon is optimized for 16px. -// .mega-octicon is optimized for 32px but can be used larger. -.octicon, .mega-octicon { - font: normal normal normal 16px/1 octicons; - display: inline-block; - text-decoration: none; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.mega-octicon { font-size: 32px; } - -.octicon-alert:before { content: '\f02d'} /*  */ -.octicon-arrow-down:before { content: '\f03f'} /*  */ -.octicon-arrow-left:before { content: '\f040'} /*  */ -.octicon-arrow-right:before { content: '\f03e'} /*  */ -.octicon-arrow-small-down:before { content: '\f0a0'} /*  */ -.octicon-arrow-small-left:before { content: '\f0a1'} /*  */ -.octicon-arrow-small-right:before { content: '\f071'} /*  */ -.octicon-arrow-small-up:before { content: '\f09f'} /*  */ -.octicon-arrow-up:before { content: '\f03d'} /*  */ -.octicon-microscope:before, -.octicon-beaker:before { content: '\f0dd'} /*  */ -.octicon-bell:before { content: '\f0de'} /*  */ -.octicon-book:before { content: '\f007'} /*  */ -.octicon-bookmark:before { content: '\f07b'} /*  */ -.octicon-briefcase:before { content: '\f0d3'} /*  */ -.octicon-broadcast:before { content: '\f048'} /*  */ -.octicon-browser:before { content: '\f0c5'} /*  */ -.octicon-bug:before { content: '\f091'} /*  */ -.octicon-calendar:before { content: '\f068'} /*  */ -.octicon-check:before { content: '\f03a'} /*  */ -.octicon-checklist:before { content: '\f076'} /*  */ -.octicon-chevron-down:before { content: '\f0a3'} /*  */ -.octicon-chevron-left:before { content: '\f0a4'} /*  */ -.octicon-chevron-right:before { content: '\f078'} /*  */ -.octicon-chevron-up:before { content: '\f0a2'} /*  */ -.octicon-circle-slash:before { content: '\f084'} /*  */ -.octicon-circuit-board:before { content: '\f0d6'} /*  */ -.octicon-clippy:before { content: '\f035'} /*  */ -.octicon-clock:before { content: '\f046'} /*  */ -.octicon-cloud-download:before { content: '\f00b'} /*  */ -.octicon-cloud-upload:before { content: '\f00c'} /*  */ -.octicon-code:before { content: '\f05f'} /*  */ -.octicon-color-mode:before { content: '\f065'} /*  */ -.octicon-comment-add:before, -.octicon-comment:before { content: '\f02b'} /*  */ -.octicon-comment-discussion:before { content: '\f04f'} /*  */ -.octicon-credit-card:before { content: '\f045'} /*  */ -.octicon-dash:before { content: '\f0ca'} /*  */ -.octicon-dashboard:before { content: '\f07d'} /*  */ -.octicon-database:before { content: '\f096'} /*  */ -.octicon-clone:before, -.octicon-desktop-download:before { content: '\f0dc'} /*  */ -.octicon-device-camera:before { content: '\f056'} /*  */ -.octicon-device-camera-video:before { content: '\f057'} /*  */ -.octicon-device-desktop:before { content: '\f27c'} /*  */ -.octicon-device-mobile:before { content: '\f038'} /*  */ -.octicon-diff:before { content: '\f04d'} /*  */ -.octicon-diff-added:before { content: '\f06b'} /*  */ -.octicon-diff-ignored:before { content: '\f099'} /*  */ -.octicon-diff-modified:before { content: '\f06d'} /*  */ -.octicon-diff-removed:before { content: '\f06c'} /*  */ -.octicon-diff-renamed:before { content: '\f06e'} /*  */ -.octicon-ellipsis:before { content: '\f09a'} /*  */ -.octicon-eye-unwatch:before, -.octicon-eye-watch:before, -.octicon-eye:before { content: '\f04e'} /*  */ -.octicon-file-binary:before { content: '\f094'} /*  */ -.octicon-file-code:before { content: '\f010'} /*  */ -.octicon-file-directory:before { content: '\f016'} /*  */ -.octicon-file-media:before { content: '\f012'} /*  */ -.octicon-file-pdf:before { content: '\f014'} /*  */ -.octicon-file-submodule:before { content: '\f017'} /*  */ -.octicon-file-symlink-directory:before { content: '\f0b1'} /*  */ -.octicon-file-symlink-file:before { content: '\f0b0'} /*  */ -.octicon-file-text:before { content: '\f011'} /*  */ -.octicon-file-zip:before { content: '\f013'} /*  */ -.octicon-flame:before { content: '\f0d2'} /*  */ -.octicon-fold:before { content: '\f0cc'} /*  */ -.octicon-gear:before { content: '\f02f'} /*  */ -.octicon-gift:before { content: '\f042'} /*  */ -.octicon-gist:before { content: '\f00e'} /*  */ -.octicon-gist-secret:before { content: '\f08c'} /*  */ -.octicon-git-branch-create:before, -.octicon-git-branch-delete:before, -.octicon-git-branch:before { content: '\f020'} /*  */ -.octicon-git-commit:before { content: '\f01f'} /*  */ -.octicon-git-compare:before { content: '\f0ac'} /*  */ -.octicon-git-merge:before { content: '\f023'} /*  */ -.octicon-git-pull-request-abandoned:before, -.octicon-git-pull-request:before { content: '\f009'} /*  */ -.octicon-globe:before { content: '\f0b6'} /*  */ -.octicon-graph:before { content: '\f043'} /*  */ -.octicon-heart:before { content: '\2665'} /* ♥ */ -.octicon-history:before { content: '\f07e'} /*  */ -.octicon-home:before { content: '\f08d'} /*  */ -.octicon-horizontal-rule:before { content: '\f070'} /*  */ -.octicon-hubot:before { content: '\f09d'} /*  */ -.octicon-inbox:before { content: '\f0cf'} /*  */ -.octicon-info:before { content: '\f059'} /*  */ -.octicon-issue-closed:before { content: '\f028'} /*  */ -.octicon-issue-opened:before { content: '\f026'} /*  */ -.octicon-issue-reopened:before { content: '\f027'} /*  */ -.octicon-jersey:before { content: '\f019'} /*  */ -.octicon-key:before { content: '\f049'} /*  */ -.octicon-keyboard:before { content: '\f00d'} /*  */ -.octicon-law:before { content: '\f0d8'} /*  */ -.octicon-light-bulb:before { content: '\f000'} /*  */ -.octicon-link:before { content: '\f05c'} /*  */ -.octicon-link-external:before { content: '\f07f'} /*  */ -.octicon-list-ordered:before { content: '\f062'} /*  */ -.octicon-list-unordered:before { content: '\f061'} /*  */ -.octicon-location:before { content: '\f060'} /*  */ -.octicon-gist-private:before, -.octicon-mirror-private:before, -.octicon-git-fork-private:before, -.octicon-lock:before { content: '\f06a'} /*  */ -.octicon-logo-github:before { content: '\f092'} /*  */ -.octicon-mail:before { content: '\f03b'} /*  */ -.octicon-mail-read:before { content: '\f03c'} /*  */ -.octicon-mail-reply:before { content: '\f051'} /*  */ -.octicon-mark-github:before { content: '\f00a'} /*  */ -.octicon-markdown:before { content: '\f0c9'} /*  */ -.octicon-megaphone:before { content: '\f077'} /*  */ -.octicon-mention:before { content: '\f0be'} /*  */ -.octicon-milestone:before { content: '\f075'} /*  */ -.octicon-mirror-public:before, -.octicon-mirror:before { content: '\f024'} /*  */ -.octicon-mortar-board:before { content: '\f0d7'} /*  */ -.octicon-mute:before { content: '\f080'} /*  */ -.octicon-no-newline:before { content: '\f09c'} /*  */ -.octicon-octoface:before { content: '\f008'} /*  */ -.octicon-organization:before { content: '\f037'} /*  */ -.octicon-package:before { content: '\f0c4'} /*  */ -.octicon-paintcan:before { content: '\f0d1'} /*  */ -.octicon-pencil:before { content: '\f058'} /*  */ -.octicon-person-add:before, -.octicon-person-follow:before, -.octicon-person:before { content: '\f018'} /*  */ -.octicon-pin:before { content: '\f041'} /*  */ -.octicon-plug:before { content: '\f0d4'} /*  */ -.octicon-repo-create:before, -.octicon-gist-new:before, -.octicon-file-directory-create:before, -.octicon-file-add:before, -.octicon-plus:before { content: '\f05d'} /*  */ -.octicon-primitive-dot:before { content: '\f052'} /*  */ -.octicon-primitive-square:before { content: '\f053'} /*  */ -.octicon-pulse:before { content: '\f085'} /*  */ -.octicon-question:before { content: '\f02c'} /*  */ -.octicon-quote:before { content: '\f063'} /*  */ -.octicon-radio-tower:before { content: '\f030'} /*  */ -.octicon-repo-delete:before, -.octicon-repo:before { content: '\f001'} /*  */ -.octicon-repo-clone:before { content: '\f04c'} /*  */ -.octicon-repo-force-push:before { content: '\f04a'} /*  */ -.octicon-gist-fork:before, -.octicon-repo-forked:before { content: '\f002'} /*  */ -.octicon-repo-pull:before { content: '\f006'} /*  */ -.octicon-repo-push:before { content: '\f005'} /*  */ -.octicon-rocket:before { content: '\f033'} /*  */ -.octicon-rss:before { content: '\f034'} /*  */ -.octicon-ruby:before { content: '\f047'} /*  */ -.octicon-screen-full:before { content: '\f066'} /*  */ -.octicon-screen-normal:before { content: '\f067'} /*  */ -.octicon-search-save:before, -.octicon-search:before { content: '\f02e'} /*  */ -.octicon-server:before { content: '\f097'} /*  */ -.octicon-settings:before { content: '\f07c'} /*  */ -.octicon-shield:before { content: '\f0e1'} /*  */ -.octicon-log-in:before, -.octicon-sign-in:before { content: '\f036'} /*  */ -.octicon-log-out:before, -.octicon-sign-out:before { content: '\f032'} /*  */ -.octicon-squirrel:before { content: '\f0b2'} /*  */ -.octicon-star-add:before, -.octicon-star-delete:before, -.octicon-star:before { content: '\f02a'} /*  */ -.octicon-stop:before { content: '\f08f'} /*  */ -.octicon-repo-sync:before, -.octicon-sync:before { content: '\f087'} /*  */ -.octicon-tag-remove:before, -.octicon-tag-add:before, -.octicon-tag:before { content: '\f015'} /*  */ -.octicon-telescope:before { content: '\f088'} /*  */ -.octicon-terminal:before { content: '\f0c8'} /*  */ -.octicon-three-bars:before { content: '\f05e'} /*  */ -.octicon-thumbsdown:before { content: '\f0db'} /*  */ -.octicon-thumbsup:before { content: '\f0da'} /*  */ -.octicon-tools:before { content: '\f031'} /*  */ -.octicon-trashcan:before { content: '\f0d0'} /*  */ -.octicon-triangle-down:before { content: '\f05b'} /*  */ -.octicon-triangle-left:before { content: '\f044'} /*  */ -.octicon-triangle-right:before { content: '\f05a'} /*  */ -.octicon-triangle-up:before { content: '\f0aa'} /*  */ -.octicon-unfold:before { content: '\f039'} /*  */ -.octicon-unmute:before { content: '\f0ba'} /*  */ -.octicon-versions:before { content: '\f064'} /*  */ -.octicon-watch:before { content: '\f0e0'} /*  */ -.octicon-remove-close:before, -.octicon-x:before { content: '\f081'} /*  */ -.octicon-zap:before { content: '\26A1'} /* ⚡ */ diff --git a/src/vs/base/browser/ui/progressbar/progressbar.ts b/src/vs/base/browser/ui/progressbar/progressbar.ts index a8e247af55a..ce3a86a4d30 100644 --- a/src/vs/base/browser/ui/progressbar/progressbar.ts +++ b/src/vs/base/browser/ui/progressbar/progressbar.ts @@ -10,6 +10,7 @@ import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; import { removeClasses, addClass, hasClass, addClasses, removeClass, hide, show } from 'vs/base/browser/dom'; import { RunOnceScheduler } from 'vs/base/common/async'; +import { isNumber } from 'vs/base/common/types'; const css_done = 'done'; const css_active = 'active'; @@ -146,7 +147,7 @@ export class ProgressBar extends Disposable { * Finds out if this progress bar is configured with total work */ hasTotal(): boolean { - return !isNaN(this.totalWork as number); + return isNumber(this.totalWork); } /** @@ -172,10 +173,11 @@ export class ProgressBar extends Disposable { } private doSetWorked(value: number): ProgressBar { - assert.ok(!isNaN(this.totalWork as number), 'Total work not set'); + assert.ok(isNumber(this.totalWork), 'Total work not set'); + const totalWork = this.totalWork!; this.workedVal = value; - this.workedVal = Math.min(this.totalWork as number, this.workedVal); + this.workedVal = Math.min(totalWork, this.workedVal); if (hasClass(this.element, css_infinite)) { removeClass(this.element, css_infinite); @@ -193,7 +195,7 @@ export class ProgressBar extends Disposable { addClass(this.element, css_discrete); } - this.bit.style.width = 100 * (this.workedVal / (this.totalWork as number)) + '%'; + this.bit.style.width = 100 * (this.workedVal / (totalWork)) + '%'; return this; } diff --git a/src/vs/base/browser/ui/sash/sash.css b/src/vs/base/browser/ui/sash/sash.css index 94ea3182c95..27be21169e7 100644 --- a/src/vs/base/browser/ui/sash/sash.css +++ b/src/vs/base/browser/ui/sash/sash.css @@ -5,7 +5,7 @@ .monaco-sash { position: absolute; - z-index: 90; + z-index: 35; touch-action: none; } @@ -84,6 +84,7 @@ .monaco-sash.disabled { cursor: default !important; + pointer-events: none !important; } /** Touch **/ @@ -98,10 +99,14 @@ /** Debug **/ -.monaco-sash.debug:not(.disabled) { +.monaco-sash.debug { background: cyan; } +.monaco-sash.debug.disabled { + background: rgba(0, 255, 255, 0.2); +} + .monaco-sash.debug:not(.disabled).orthogonal-start::before, .monaco-sash.debug:not(.disabled).orthogonal-end::after { background: red; diff --git a/src/vs/base/browser/ui/sash/sash.ts b/src/vs/base/browser/ui/sash/sash.ts index 8c7168bad53..e394df1e790 100644 --- a/src/vs/base/browser/ui/sash/sash.ts +++ b/src/vs/base/browser/ui/sash/sash.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./sash'; -import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { isIPad } from 'vs/base/browser/browser'; import { isMacintosh } from 'vs/base/common/platform'; import * as types from 'vs/base/common/types'; @@ -61,7 +61,7 @@ export class Sash extends Disposable { private el: HTMLElement; private layoutProvider: ISashLayoutProvider; private hidden: boolean; - private orientation: Orientation; + private orientation!: Orientation; private _state: SashState = SashState.Enabled; get state(): SashState { return this._state; } @@ -95,14 +95,14 @@ export class Sash extends Disposable { linkedSash: Sash | undefined = undefined; - private orthogonalStartSashDisposables: IDisposable[] = []; + private readonly orthogonalStartSashDisposables = this._register(new DisposableStore()); private _orthogonalStartSash: Sash | undefined; get orthogonalStartSash(): Sash | undefined { return this._orthogonalStartSash; } set orthogonalStartSash(sash: Sash | undefined) { - this.orthogonalStartSashDisposables = dispose(this.orthogonalStartSashDisposables); + this.orthogonalStartSashDisposables.clear(); if (sash) { - sash.onDidEnablementChange(this.onOrthogonalStartSashEnablementChange, this, this.orthogonalStartSashDisposables); + this.orthogonalStartSashDisposables.add(sash.onDidEnablementChange(this.onOrthogonalStartSashEnablementChange, this)); this.onOrthogonalStartSashEnablementChange(sash.state); } else { this.onOrthogonalStartSashEnablementChange(SashState.Disabled); @@ -111,14 +111,14 @@ export class Sash extends Disposable { this._orthogonalStartSash = sash; } - private orthogonalEndSashDisposables: IDisposable[] = []; + private readonly orthogonalEndSashDisposables = this._register(new DisposableStore()); private _orthogonalEndSash: Sash | undefined; get orthogonalEndSash(): Sash | undefined { return this._orthogonalEndSash; } set orthogonalEndSash(sash: Sash | undefined) { - this.orthogonalEndSashDisposables = dispose(this.orthogonalEndSashDisposables); + this.orthogonalEndSashDisposables.clear(); if (sash) { - sash.onDidEnablementChange(this.onOrthogonalEndSashEnablementChange, this, this.orthogonalEndSashDisposables); + this.orthogonalEndSashDisposables.add(sash.onDidEnablementChange(this.onOrthogonalEndSashEnablementChange, this)); this.onOrthogonalEndSashEnablementChange(sash.state); } else { this.onOrthogonalEndSashEnablementChange(SashState.Disabled); @@ -212,7 +212,13 @@ export class Sash extends Disposable { return; } - const iframes = getElementsByTagName('iframe'); + // Select both iframes and webviews; internally Electron nests an iframe + // in its component, but this isn't queryable. + const iframes = [ + ...getElementsByTagName('iframe'), + ...getElementsByTagName('webview'), + ]; + for (const iframe of iframes) { iframe.style.pointerEvents = 'none'; // disable mouse events on iframes as long as we drag the sash } @@ -254,7 +260,7 @@ export class Sash extends Disposable { style.innerHTML = `* { cursor: ${cursor} !important; }`; }; - const disposables: IDisposable[] = []; + const disposables = new DisposableStore(); updateStyle(); @@ -278,9 +284,8 @@ export class Sash extends Disposable { removeClass(this.el, 'active'); this._onDidEnd.fire(); - dispose(disposables); + disposables.dispose(); - const iframes = getElementsByTagName('iframe'); for (const iframe of iframes) { iframe.style.pointerEvents = 'auto'; } @@ -384,9 +389,6 @@ export class Sash extends Disposable { dispose(): void { super.dispose(); - this.orthogonalStartSashDisposables = dispose(this.orthogonalStartSashDisposables); - this.orthogonalEndSashDisposables = dispose(this.orthogonalEndSashDisposables); - if (this.el && this.el.parentElement) { this.el.parentElement.removeChild(this.el); } diff --git a/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts b/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts index 7de8f3fa766..4e9245ade07 100644 --- a/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts @@ -49,7 +49,7 @@ export abstract class AbstractScrollbar extends Widget { private _mouseMoveMonitor: GlobalMouseMoveMonitor; public domNode: FastDomNode; - public slider: FastDomNode; + public slider!: FastDomNode; protected _shouldRender: boolean; @@ -108,6 +108,12 @@ export abstract class AbstractScrollbar extends Widget { this._sliderMouseDown(e, () => { /*nothing to do*/ }); } }); + + this.onclick(this.slider.domNode, e => { + if (e.leftButton) { + e.stopPropagation(); + } + }); } // ----------------- Update state diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts index 9b31c847f70..f7216dfdb10 100644 --- a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +++ b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/scrollbars'; +import { isEdgeOrIE } from 'vs/base/browser/browser'; import * as dom from 'vs/base/browser/dom'; import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode'; import { IMouseEvent, StandardWheelEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; @@ -147,9 +148,9 @@ export abstract class AbstractScrollableElement extends Widget { private readonly _horizontalScrollbar: HorizontalScrollbar; private readonly _domNode: HTMLElement; - private readonly _leftShadowDomNode: FastDomNode; - private readonly _topShadowDomNode: FastDomNode; - private readonly _topLeftShadowDomNode: FastDomNode; + private readonly _leftShadowDomNode: FastDomNode | null; + private readonly _topShadowDomNode: FastDomNode | null; + private readonly _topLeftShadowDomNode: FastDomNode | null; private readonly _listenOnDomNode: HTMLElement; @@ -206,6 +207,10 @@ export abstract class AbstractScrollableElement extends Widget { this._topLeftShadowDomNode = createFastDomNode(document.createElement('div')); this._topLeftShadowDomNode.setClassName('shadow top-left-corner'); this._domNode.appendChild(this._topLeftShadowDomNode.domNode); + } else { + this._leftShadowDomNode = null; + this._topShadowDomNode = null; + this._topLeftShadowDomNode = null; } this._listenOnDomNode = this._options.listenOnDomNode || this._domNode; @@ -312,7 +317,7 @@ export abstract class AbstractScrollableElement extends Widget { this._onMouseWheel(new StandardWheelEvent(browserEvent)); }; - this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, 'mousewheel', onMouseWheel)); + this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, isEdgeOrIE ? 'mousewheel' : 'wheel', onMouseWheel)); } } @@ -429,9 +434,9 @@ export abstract class AbstractScrollableElement extends Widget { let enableTop = scrollState.scrollTop > 0; let enableLeft = scrollState.scrollLeft > 0; - this._leftShadowDomNode.setClassName('shadow' + (enableLeft ? ' left' : '')); - this._topShadowDomNode.setClassName('shadow' + (enableTop ? ' top' : '')); - this._topLeftShadowDomNode.setClassName('shadow top-left-corner' + (enableTop ? ' top' : '') + (enableLeft ? ' left' : '')); + this._leftShadowDomNode!.setClassName('shadow' + (enableLeft ? ' left' : '')); + this._topShadowDomNode!.setClassName('shadow' + (enableTop ? ' top' : '')); + this._topLeftShadowDomNode!.setClassName('shadow top-left-corner' + (enableTop ? ' top' : '') + (enableLeft ? ' left' : '')); } } @@ -523,7 +528,7 @@ export class DomScrollableElement extends ScrollableElement { } public scanDomNode(): void { - // widh, scrollLeft, scrollWidth, height, scrollTop, scrollHeight + // width, scrollLeft, scrollWidth, height, scrollTop, scrollHeight this.setScrollDimensions({ width: this._element.clientWidth, scrollWidth: this._element.scrollWidth, diff --git a/src/vs/base/browser/ui/selectBox/selectBox.ts b/src/vs/base/browser/ui/selectBox/selectBox.ts index 0e7314fd285..d450f76d360 100644 --- a/src/vs/base/browser/ui/selectBox/selectBox.ts +++ b/src/vs/base/browser/ui/selectBox/selectBox.ts @@ -8,26 +8,26 @@ import 'vs/css!./selectBox'; import { Event } from 'vs/base/common/event'; import { Widget } from 'vs/base/browser/ui/widget'; import { Color } from 'vs/base/common/color'; -import { deepClone, mixin } from 'vs/base/common/objects'; +import { deepClone } from 'vs/base/common/objects'; import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview'; import { IListStyles } from 'vs/base/browser/ui/list/listWidget'; import { SelectBoxNative } from 'vs/base/browser/ui/selectBox/selectBoxNative'; import { SelectBoxList } from 'vs/base/browser/ui/selectBox/selectBoxCustom'; import { isMacintosh } from 'vs/base/common/platform'; +import { IDisposable } from 'vs/base/common/lifecycle'; // Public SelectBox interface - Calls routed to appropriate select implementation class -export interface ISelectBoxDelegate { +export interface ISelectBoxDelegate extends IDisposable { // Public SelectBox Interface readonly onDidSelect: Event; - setOptions(options: ISelectOptionItem[], selected?: number); + setOptions(options: ISelectOptionItem[], selected?: number): void; select(index: number): void; - setAriaLabel(label: string); + setAriaLabel(label: string): void; focus(): void; blur(): void; - dispose(): void; // Delegated Widget interface render(container: HTMLElement): void; @@ -72,14 +72,11 @@ export interface ISelectData { } export class SelectBox extends Widget implements ISelectBoxDelegate { - private styles: ISelectBoxStyles; private selectBoxDelegate: ISelectBoxDelegate; constructor(options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles = deepClone(defaultStyles), selectBoxOptions?: ISelectBoxOptions) { super(); - mixin(this.styles, defaultStyles, false); - // Default to native SelectBox for OSX unless overridden if (isMacintosh && !(selectBoxOptions && selectBoxOptions.useCustomDrawn)) { this.selectBoxDelegate = new SelectBoxNative(options, selected, styles, selectBoxOptions); @@ -129,4 +126,4 @@ export class SelectBox extends Widget implements ISelectBoxDelegate { public applyStyles(): void { this.selectBoxDelegate.applyStyles(); } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts index 189f657a716..134c64bbef4 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts +++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts @@ -5,7 +5,7 @@ import 'vs/css!./selectBoxCustom'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; import { KeyCode, KeyCodeUtils } from 'vs/base/common/keyCodes'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; @@ -38,8 +38,8 @@ class SelectListRenderer implements IListRendererObject.create(null); + renderTemplate(container: HTMLElement): ISelectListTemplateData { + const data: ISelectListTemplateData = Object.create(null); data.disposables = []; data.root = container; data.text = dom.append(container, $('.option-text')); @@ -51,10 +51,10 @@ class SelectListRenderer implements IListRenderertemplateData; - const text = (element).text; - const decoratorRight = (element).decoratorRight; - const isDisabled = (element).isDisabled; + const data: ISelectListTemplateData = templateData; + const text = element.text; + const decoratorRight = element.decoratorRight; + const isDisabled = element.isDisabled; data.text.textContent = text; data.decoratorRight.innerText = (!!decoratorRight ? decoratorRight : ''); @@ -68,10 +68,10 @@ class SelectListRenderer implements IListRendererdata.root), 'option-disabled'); + dom.addClass(data.root, 'option-disabled'); } else { // Make sure we do class removal from prior template rendering - dom.removeClass((data.root), 'option-disabled'); + dom.removeClass(data.root, 'option-disabled'); } } @@ -80,7 +80,7 @@ class SelectListRenderer implements IListRenderer { +export class SelectBoxList extends Disposable implements ISelectBoxDelegate, IListVirtualDelegate { private static readonly DEFAULT_DROPDOWN_MINIMUM_BOTTOM_MARGIN = 32; private static readonly DEFAULT_DROPDOWN_MINIMUM_TOP_MARGIN = 2; @@ -89,29 +89,28 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate; - private toDispose: IDisposable[]; private styles: ISelectBoxStyles; - private listRenderer: SelectListRenderer; - private contextViewProvider: IContextViewProvider; - private selectDropDownContainer: HTMLElement; - private styleElement: HTMLStyleElement; - private selectList: List; - private selectDropDownListContainer: HTMLElement; - private widthControlElement: HTMLElement; - private _currentSelection: number; - private _dropDownPosition: AnchorPosition; + private listRenderer!: SelectListRenderer; + private contextViewProvider!: IContextViewProvider; + private selectDropDownContainer!: HTMLElement; + private styleElement!: HTMLStyleElement; + private selectList!: List; + private selectDropDownListContainer!: HTMLElement; + private widthControlElement!: HTMLElement; + private _currentSelection = 0; + private _dropDownPosition!: AnchorPosition; private _hasDetails: boolean = false; - private selectionDetailsPane: HTMLElement; + private selectionDetailsPane!: HTMLElement; private _skipLayout: boolean = false; private _sticky: boolean = false; // for dev purposes only constructor(options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles, selectBoxOptions?: ISelectBoxOptions) { - this.toDispose = []; + super(); this._isVisible = false; this.selectBoxOptions = selectBoxOptions || Object.create(null); @@ -123,12 +122,6 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate(); - this.toDispose.push(this._onDidSelect); + this._register(this._onDidSelect); this.styles = styles; @@ -191,18 +184,21 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate { + this._register(dom.addStandardDisposableListener(this.selectElement, 'change', (e) => { this.selected = e.target.selectedIndex; this._onDidSelect.fire({ index: e.target.selectedIndex, selected: e.target.value }); + if (!!this.options[this.selected] && !!this.options[this.selected].text) { + this.selectElement.title = this.options[this.selected].text; + } })); // Have to implement both keyboard and mouse controllers to handle disabled options // Intercept mouse events to override normal select actions on parents - this.toDispose.push(dom.addDisposableListener(this.selectElement, dom.EventType.CLICK, (e) => { + this._register(dom.addDisposableListener(this.selectElement, dom.EventType.CLICK, (e) => { dom.EventHelper.stop(e); if (this._isVisible) { @@ -212,13 +208,13 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate { + this._register(dom.addDisposableListener(this.selectElement, dom.EventType.MOUSE_DOWN, (e) => { dom.EventHelper.stop(e); })); // Intercept keyboard handling - this.toDispose.push(dom.addDisposableListener(this.selectElement, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => { + this._register(dom.addDisposableListener(this.selectElement, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => { const event = new StandardKeyboardEvent(e); let showDropDown = false; @@ -245,7 +241,7 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate this.selectList.length > 0) .map(e => new StandardKeyboardEvent(e)); - onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.Enter).on(e => this.onEnter(e), this, this.toDispose); - onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.Escape).on(e => this.onEscape(e), this, this.toDispose); - onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.UpArrow).on(this.onUpArrow, this, this.toDispose); - onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.DownArrow).on(this.onDownArrow, this, this.toDispose); - onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.PageDown).on(this.onPageDown, this, this.toDispose); - onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.PageUp).on(this.onPageUp, this, this.toDispose); - onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.Home).on(this.onHome, this, this.toDispose); - onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.End).on(this.onEnd, this, this.toDispose); - onSelectDropDownKeyDown.filter(e => (e.keyCode >= KeyCode.KEY_0 && e.keyCode <= KeyCode.KEY_Z) || (e.keyCode >= KeyCode.US_SEMICOLON && e.keyCode <= KeyCode.NUMPAD_DIVIDE)).on(this.onCharacter, this, this.toDispose); + 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.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)); + this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.End).on(this.onEnd, this)); + this._register(onSelectDropDownKeyDown.filter(e => (e.keyCode >= KeyCode.KEY_0 && e.keyCode <= KeyCode.KEY_Z) || (e.keyCode >= KeyCode.US_SEMICOLON && e.keyCode <= KeyCode.NUMPAD_DIVIDE)).on(this.onCharacter, this)); // SetUp list mouse controller - control navigation, disabled items, focus - Event.chain(domEvent(this.selectList.getHTMLElement(), 'mouseup')) + this._register(Event.chain(domEvent(this.selectList.getHTMLElement(), 'mouseup')) .filter(() => this.selectList.length > 0) - .on(e => this.onMouseUp(e), this, this.toDispose); + .on(e => this.onMouseUp(e), this)); - this.toDispose.push( - this.selectList.onDidBlur(_ => this.onListBlur()), - this.selectList.onMouseOver(e => typeof e.index !== 'undefined' && this.selectList.setFocus([e.index])), - this.selectList.onFocusChange(e => this.onListFocus(e)) - ); + + this._register(this.selectList.onDidBlur(_ => this.onListBlur())); + this._register(this.selectList.onMouseOver(e => typeof e.index !== 'undefined' && this.selectList.setFocus([e.index]))); + this._register(this.selectList.onFocusChange(e => this.onListFocus(e))); this.selectList.getHTMLElement().setAttribute('aria-label', this.selectBoxOptions.ariaLabel || ''); this.selectList.getHTMLElement().setAttribute('aria-expanded', 'true'); @@ -811,7 +802,11 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate { for (let i = 0; i < element.childNodes.length; i++) { - const child = element.childNodes.item(i); + const child = element.childNodes.item(i); - const tagName = (child).tagName && (child).tagName.toLowerCase(); + const tagName = child.tagName && child.tagName.toLowerCase(); if (tagName === 'img') { element.removeChild(child); } else { @@ -861,8 +856,8 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate; - private toDispose: IDisposable[]; private styles: ISelectBoxStyles; constructor(options: ISelectOptionItem[], selected: number, styles: ISelectBoxStyles, selectBoxOptions?: ISelectBoxOptions) { - this.toDispose = []; + super(); this.selectBoxOptions = selectBoxOptions || Object.create(null); this.options = []; this.selectElement = document.createElement('select'); - // Workaround for Electron 2.x - // Native select should not require explicit role attribute, however, Electron 2.x - // incorrectly exposes select as menuItem which interferes with labeling and results - // in the unlabeled not been read. Electron 3 appears to fix. - this.selectElement.setAttribute('role', 'combobox'); - this.selectElement.className = 'monaco-select-box'; if (typeof this.selectBoxOptions.ariaLabel === 'string') { this.selectElement.setAttribute('aria-label', this.selectBoxOptions.ariaLabel); } - this._onDidSelect = new Emitter(); - this.toDispose.push(this._onDidSelect); + this._onDidSelect = this._register(new Emitter()); this.styles = styles; @@ -52,7 +44,7 @@ export class SelectBoxNative implements ISelectBoxDelegate { private registerListeners() { - this.toDispose.push(dom.addStandardDisposableListener(this.selectElement, 'change', (e) => { + this._register(dom.addStandardDisposableListener(this.selectElement, 'change', (e) => { this.selectElement.title = e.target.value; this._onDidSelect.fire({ index: e.target.selectedIndex, @@ -60,7 +52,7 @@ export class SelectBoxNative implements ISelectBoxDelegate { }); })); - this.toDispose.push(dom.addStandardDisposableListener(this.selectElement, 'keydown', (e) => { + this._register(dom.addStandardDisposableListener(this.selectElement, 'keydown', (e) => { let showSelect = false; if (isMacintosh) { @@ -115,7 +107,7 @@ export class SelectBoxNative implements ISelectBoxDelegate { } this.selectElement.selectedIndex = this.selected; - if (this.options.length && typeof this.options[this.selected].text === 'string') { + if ((this.selected < this.options.length) && typeof this.options[this.selected].text === 'string') { this.selectElement.title = this.options[this.selected].text; } else { this.selectElement.title = ''; @@ -174,8 +166,4 @@ export class SelectBoxNative implements ISelectBoxDelegate { return option; } - - public dispose(): void { - this.toDispose = dispose(this.toDispose); - } } diff --git a/src/vs/base/browser/ui/splitview/arrow-collapse-dark.svg b/src/vs/base/browser/ui/splitview/arrow-collapse-dark.svg deleted file mode 100644 index 6f3abfce784..00000000000 --- a/src/vs/base/browser/ui/splitview/arrow-collapse-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/splitview/arrow-collapse.svg b/src/vs/base/browser/ui/splitview/arrow-collapse.svg deleted file mode 100644 index 5dcb87c772c..00000000000 --- a/src/vs/base/browser/ui/splitview/arrow-collapse.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/splitview/arrow-expand-dark.svg b/src/vs/base/browser/ui/splitview/arrow-expand-dark.svg deleted file mode 100644 index 22dfac04f15..00000000000 --- a/src/vs/base/browser/ui/splitview/arrow-expand-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/splitview/arrow-expand.svg b/src/vs/base/browser/ui/splitview/arrow-expand.svg deleted file mode 100644 index e55ccd923e5..00000000000 --- a/src/vs/base/browser/ui/splitview/arrow-expand.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/splitview/panelview.css b/src/vs/base/browser/ui/splitview/panelview.css index 4801a2bd3a9..d4def58461f 100644 --- a/src/vs/base/browser/ui/splitview/panelview.css +++ b/src/vs/base/browser/ui/splitview/panelview.css @@ -27,23 +27,31 @@ } .monaco-panel-view .panel > .panel-header { - background-image: url('arrow-collapse.svg'); + background-image: url('tree-collapsed-light.svg'); background-position: 2px center; background-repeat: no-repeat; } .monaco-panel-view .panel > .panel-header.expanded { - background-image: url('arrow-expand.svg'); + background-image: url('tree-expanded-light.svg'); background-position: 2px center; background-repeat: no-repeat; } .vs-dark .monaco-panel-view .panel > .panel-header { - background-image: url('arrow-collapse-dark.svg'); + background-image: url('tree-collapsed-dark.svg'); } .vs-dark .monaco-panel-view .panel > .panel-header.expanded { - background-image: url('arrow-expand-dark.svg'); + background-image: url('tree-expanded-dark.svg'); +} + +.hc-black .monaco-panel-view .panel > .panel-header { + background-image: url('tree-collapsed-hc.svg'); +} + +.hc-black .monaco-panel-view .panel > .panel-header.expanded { + background-image: url('tree-expanded-hc.svg'); } /* TODO: actions should be part of the panel, but they aren't yet */ diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts index a78bb77de5e..7c337dc62da 100644 --- a/src/vs/base/browser/ui/splitview/panelview.ts +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./panelview'; -import { IDisposable, dispose, combinedDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; @@ -37,14 +37,15 @@ export interface IPanelStyles { * Subclasses wouldn't be able to set own properties * before the `render()` call, thus forbiding their use. */ -export abstract class Panel implements IView { +export abstract class Panel extends Disposable implements IView { private static readonly HEADER_SIZE = 22; readonly element: HTMLElement; + private header!: HTMLElement; + private body!: HTMLElement; protected _expanded: boolean; - protected disposables: IDisposable[] = []; private expandedSize: number | undefined = undefined; private _headerVisible = true; @@ -52,10 +53,9 @@ export abstract class Panel implements IView { private _maximumBodySize: number; private ariaHeaderLabel: string; private styles: IPanelStyles = {}; + private animationTimer: number | undefined = undefined; - private header: HTMLElement; - - private _onDidChange = new Emitter(); + private readonly _onDidChange = this._register(new Emitter()); readonly onDidChange: Event = this._onDidChange.event; get draggableElement(): HTMLElement { @@ -109,7 +109,10 @@ export abstract class Panel implements IView { return headerSize + maximumBodySize; } + width: number = 0; + constructor(options: IPanelOptions = {}) { + super(); this._expanded = typeof options.expanded === 'undefined' ? true : !!options.expanded; this.ariaHeaderLabel = options.ariaHeaderLabel || ''; this._minimumBodySize = typeof options.minimumBodySize === 'number' ? options.minimumBodySize : 120; @@ -129,8 +132,19 @@ export abstract class Panel implements IView { this._expanded = !!expanded; this.updateHeader(); - this._onDidChange.fire(expanded ? this.expandedSize : undefined); + if (expanded) { + if (typeof this.animationTimer === 'number') { + clearTimeout(this.animationTimer); + } + append(this.element, this.body); + } else { + this.animationTimer = window.setTimeout(() => { + this.body.remove(); + }, 200); + } + + this._onDidChange.fire(expanded ? this.expandedSize : undefined); return true; } @@ -157,43 +171,37 @@ export abstract class Panel implements IView { this.renderHeader(this.header); const focusTracker = trackFocus(this.header); - focusTracker.onDidFocus(() => addClass(this.header, 'focused')); - focusTracker.onDidBlur(() => removeClass(this.header, 'focused')); + this._register(focusTracker); + this._register(focusTracker.onDidFocus(() => addClass(this.header, 'focused'), null)); + this._register(focusTracker.onDidBlur(() => removeClass(this.header, 'focused'), null)); this.updateHeader(); const onHeaderKeyDown = Event.chain(domEvent(this.header, 'keydown')) .map(e => new StandardKeyboardEvent(e)); - onHeaderKeyDown.filter(e => e.keyCode === KeyCode.Enter || e.keyCode === KeyCode.Space) - .event(() => this.setExpanded(!this.isExpanded()), null, this.disposables); + this._register(onHeaderKeyDown.filter(e => e.keyCode === KeyCode.Enter || e.keyCode === KeyCode.Space) + .event(() => this.setExpanded(!this.isExpanded()), null)); - onHeaderKeyDown.filter(e => e.keyCode === KeyCode.LeftArrow) - .event(() => this.setExpanded(false), null, this.disposables); + this._register(onHeaderKeyDown.filter(e => e.keyCode === KeyCode.LeftArrow) + .event(() => this.setExpanded(false), null)); - onHeaderKeyDown.filter(e => e.keyCode === KeyCode.RightArrow) - .event(() => this.setExpanded(true), null, this.disposables); + this._register(onHeaderKeyDown.filter(e => e.keyCode === KeyCode.RightArrow) + .event(() => this.setExpanded(true), null)); - domEvent(this.header, 'click') - (() => this.setExpanded(!this.isExpanded()), null, this.disposables); + this._register(domEvent(this.header, 'click') + (() => this.setExpanded(!this.isExpanded()), null)); - // TODO@Joao move this down to panelview - // onHeaderKeyDown.filter(e => e.keyCode === KeyCode.UpArrow) - // .event(focusPrevious, this, this.disposables); - - // onHeaderKeyDown.filter(e => e.keyCode === KeyCode.DownArrow) - // .event(focusNext, this, this.disposables); - - const body = append(this.element, $('.panel-body')); - this.renderBody(body); + this.body = append(this.element, $('.panel-body')); + this.renderBody(this.body); } - layout(size: number): void { + layout(height: number): void { const headerSize = this.headerVisible ? Panel.HEADER_SIZE : 0; if (this.isExpanded()) { - this.layoutBody(size - headerSize); - this.expandedSize = size; + this.layoutBody(height - headerSize, this.width); + this.expandedSize = height; } } @@ -224,13 +232,7 @@ export abstract class Panel implements IView { protected abstract renderHeader(container: HTMLElement): void; protected abstract renderBody(container: HTMLElement): void; - protected abstract layoutBody(size: number): void; - - dispose(): void { - this.disposables = dispose(this.disposables); - - this._onDidChange.dispose(); - } + protected abstract layoutBody(height: number, width: number): void; } interface IDndContext { @@ -266,7 +268,7 @@ class PanelDraggable extends Disposable { e.dataTransfer.effectAllowed = 'move'; - const dragImage = append(document.body, $('.monaco-panel-drag-image', {}, this.panel.draggableElement.textContent || '')); + const dragImage = append(document.body, $('.monaco-drag-image', {}, this.panel.draggableElement.textContent || '')); e.dataTransfer.setDragImage(dragImage, -10, -10); setTimeout(() => document.body.removeChild(dragImage), 0); @@ -369,8 +371,9 @@ export class PanelView extends Disposable { private dndContext: IDndContext = { draggable: null }; private el: HTMLElement; private panelItems: IPanelItem[] = []; + private width: number = 0; private splitview: SplitView; - private animationTimer: number | null = null; + private animationTimer: number | undefined = undefined; private _onDidDrop = this._register(new Emitter<{ from: Panel, to: Panel }>()); readonly onDidDrop: Event<{ from: Panel, to: Panel }> = this._onDidDrop.event; @@ -387,23 +390,24 @@ export class PanelView extends Disposable { } addPanel(panel: Panel, size: number, index = this.splitview.length): void { - const disposables: IDisposable[] = []; + const disposables = new DisposableStore(); // https://github.com/Microsoft/vscode/issues/59950 let shouldAnimate = false; - disposables.push(scheduleAtNextAnimationFrame(() => shouldAnimate = true)); + disposables.add(scheduleAtNextAnimationFrame(() => shouldAnimate = true)); - Event.filter(panel.onDidChange, () => shouldAnimate) - (this.setupAnimation, this, disposables); + disposables.add(Event.filter(panel.onDidChange, () => shouldAnimate) + (this.setupAnimation, this)); - const panelItem = { panel, disposable: combinedDisposable(disposables) }; + const panelItem = { panel, disposable: disposables }; this.panelItems.splice(index, 0, panelItem); + panel.width = this.width; this.splitview.addView(panel, size, index); if (this.dnd) { const draggable = new PanelDraggable(panel, this.dnd, this.dndContext); - disposables.push(draggable); - draggable.onDidDrop(this._onDidDrop.fire, this._onDidDrop, disposables); + disposables.add(draggable); + disposables.add(draggable.onDidDrop(this._onDidDrop.fire, this._onDidDrop)); } } @@ -453,8 +457,14 @@ export class PanelView extends Disposable { return this.splitview.getViewSize(index); } - layout(size: number): void { - this.splitview.layout(size); + layout(height: number, width: number): void { + this.width = width; + + for (const panelItem of this.panelItems) { + panelItem.panel.width = width; + } + + this.splitview.layout(height); } private setupAnimation(): void { @@ -465,7 +475,7 @@ export class PanelView extends Disposable { addClass(this.el, 'animated'); this.animationTimer = window.setTimeout(() => { - this.animationTimer = null; + this.animationTimer = undefined; removeClass(this.el, 'animated'); }, 200); } diff --git a/src/vs/base/browser/ui/splitview/splitview.css b/src/vs/base/browser/ui/splitview/splitview.css index 7479f5178d7..6fb8f1c61d0 100644 --- a/src/vs/base/browser/ui/splitview/splitview.css +++ b/src/vs/base/browser/ui/splitview/splitview.css @@ -41,6 +41,10 @@ position: relative; } +.monaco-split-view2 > .split-view-container > .split-view-view:not(.visible) { + display: none; +} + .monaco-split-view2.vertical > .split-view-container > .split-view-view { width: 100%; } diff --git a/src/vs/base/browser/ui/splitview/splitview.ts b/src/vs/base/browser/ui/splitview/splitview.ts index 521638ebc55..07f860ecb57 100644 --- a/src/vs/base/browser/ui/splitview/splitview.ts +++ b/src/vs/base/browser/ui/splitview/splitview.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./splitview'; -import { IDisposable, combinedDisposable, toDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable, Disposable, combinedDisposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; import * as types from 'vs/base/common/types'; import * as dom from 'vs/base/browser/dom'; @@ -47,8 +47,9 @@ export interface IView { readonly maximumSize: number; readonly onDidChange: Event; readonly priority?: LayoutPriority; - readonly snapSize?: number; + readonly snap?: boolean; layout(size: number, orientation: Orientation): void; + setVisible?(visible: boolean): void; } interface ISashEvent { @@ -58,12 +59,98 @@ interface ISashEvent { alt: boolean; } -interface IViewItem { - view: IView; - size: number; - container: HTMLElement; - disposable: IDisposable; - layout(): void; +type ViewItemSize = number | { cachedVisibleSize: number }; + +abstract class ViewItem { + + private _size: number; + set size(size: number) { + this._size = size; + } + + get size(): number { + return this._size; + } + + private _cachedVisibleSize: number | undefined = undefined; + get cachedVisibleSize(): number | undefined { return this._cachedVisibleSize; } + + get visible(): boolean { + return typeof this._cachedVisibleSize === 'undefined'; + } + + set visible(visible: boolean) { + if (visible === this.visible) { + return; + } + + if (visible) { + this.size = clamp(this._cachedVisibleSize!, this.viewMinimumSize, this.viewMaximumSize); + this._cachedVisibleSize = undefined; + } else { + this._cachedVisibleSize = this.size; + this.size = 0; + } + + dom.toggleClass(this.container, 'visible', visible); + + if (this.view.setVisible) { + this.view.setVisible(visible); + } + } + + get minimumSize(): number { return this.visible ? this.view.minimumSize : 0; } + get viewMinimumSize(): number { return this.view.minimumSize; } + + get maximumSize(): number { return this.visible ? this.view.maximumSize : 0; } + get viewMaximumSize(): number { return this.view.maximumSize; } + + get priority(): LayoutPriority | undefined { return this.view.priority; } + get snap(): boolean { return !!this.view.snap; } + + constructor( + protected container: HTMLElement, + private view: IView, + size: ViewItemSize, + private disposable: IDisposable + ) { + if (typeof size === 'number') { + this._size = size; + this._cachedVisibleSize = undefined; + } else { + this._size = 0; + this._cachedVisibleSize = size.cachedVisibleSize; + } + + dom.addClass(container, 'visible'); + } + + abstract layout(): void; + + layoutView(orientation: Orientation): void { + this.view.layout(this.size, orientation); + } + + dispose(): IView { + this.disposable.dispose(); + return this.view; + } +} + +class VerticalViewItem extends ViewItem { + + layout(): void { + this.container.style.height = `${this.size}px`; + this.layoutView(Orientation.VERTICAL); + } +} + +class HorizontalViewItem extends ViewItem { + + layout(): void { + this.container.style.width = `${this.size}px`; + this.layoutView(Orientation.HORIZONTAL); + } } interface ISashItem { @@ -71,6 +158,11 @@ interface ISashItem { disposable: IDisposable; } +interface ISashDragSnapState { + readonly index: number; + readonly limitDelta: number; +} + interface ISashDragState { index: number; start: number; @@ -79,6 +171,8 @@ interface ISashDragState { minDelta: number; maxDelta: number; alt: boolean; + snapBefore: ISashDragSnapState | undefined; + snapAfter: ISashDragSnapState | undefined; disposable: IDisposable; } @@ -89,11 +183,13 @@ enum State { export type DistributeSizing = { type: 'distribute' }; export type SplitSizing = { type: 'split', index: number }; -export type Sizing = DistributeSizing | SplitSizing; +export type InvisibleSizing = { type: 'invisible', cachedVisibleSize: number }; +export type Sizing = DistributeSizing | SplitSizing | InvisibleSizing; export namespace Sizing { export const Distribute: DistributeSizing = { type: 'distribute' }; export function Split(index: number): SplitSizing { return { type: 'split', index }; } + export function Invisible(cachedVisibleSize: number): InvisibleSizing { return { type: 'invisible', cachedVisibleSize }; } } export class SplitView extends Disposable { @@ -105,9 +201,9 @@ export class SplitView extends Disposable { private size = 0; private contentSize = 0; private proportions: undefined | number[] = undefined; - private viewItems: IViewItem[] = []; + private viewItems: ViewItem[] = []; private sashItems: ISashItem[] = []; - private sashDragState: ISashDragState; + private sashDragState: ISashDragState | undefined; private state: State = State.Idle; private inverseAltBehavior: boolean; private proportionalLayout: boolean; @@ -123,11 +219,11 @@ export class SplitView extends Disposable { } get minimumSize(): number { - return this.viewItems.reduce((r, item) => r + item.view.minimumSize, 0); + return this.viewItems.reduce((r, item) => r + item.minimumSize, 0); } get maximumSize(): number { - return this.length === 0 ? Number.POSITIVE_INFINITY : this.viewItems.reduce((r, item) => r + item.view.maximumSize, 0); + return this.length === 0 ? Number.POSITIVE_INFINITY : this.viewItems.reduce((r, item) => r + item.maximumSize, 0); } private _orthogonalStartSash: Sash | undefined; @@ -200,34 +296,30 @@ export class SplitView extends Disposable { const onChangeDisposable = view.onDidChange(size => this.onViewChange(item, size)); const containerDisposable = toDisposable(() => this.viewContainer.removeChild(container)); - const disposable = combinedDisposable([onChangeDisposable, containerDisposable]); + const disposable = combinedDisposable(onChangeDisposable, containerDisposable); - const layoutContainer = this.orientation === Orientation.VERTICAL - ? () => item.container.style.height = `${item.size}px` - : () => item.container.style.width = `${item.size}px`; - - const layout = () => { - layoutContainer(); - item.view.layout(item.size, this.orientation); - }; - - let viewSize: number; + let viewSize: ViewItemSize; if (typeof size === 'number') { viewSize = size; } else if (size.type === 'split') { viewSize = this.getViewSize(size.index) / 2; + } else if (size.type === 'invisible') { + viewSize = { cachedVisibleSize: size.cachedVisibleSize }; } else { viewSize = view.minimumSize; } - const item: IViewItem = { view, container, size: viewSize, layout, disposable }; + const item = this.orientation === Orientation.VERTICAL + ? new VerticalViewItem(container, view, viewSize, disposable) + : new HorizontalViewItem(container, view, viewSize, disposable); + this.viewItems.splice(index, 0, item); // Add sash if (this.viewItems.length > 1) { const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL; - const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: sash => this.getSashPosition(sash) } : { getVerticalSashLeft: sash => this.getSashPosition(sash) }; + const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: (sash: Sash) => this.getSashPosition(sash) } : { getVerticalSashLeft: (sash: Sash) => this.getSashPosition(sash) }; const sash = new Sash(this.sashContainer, layoutProvider, { orientation, orthogonalStartSash: this.orthogonalStartSash, @@ -235,8 +327,8 @@ export class SplitView extends Disposable { }); const sashEventMapper = this.orientation === Orientation.VERTICAL - ? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey } as ISashEvent) - : (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX, alt: e.altKey } as ISashEvent); + ? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey }) + : (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX, alt: e.altKey }); const onStart = Event.map(sash.onDidStart, sashEventMapper); const onStartDisposable = onStart(this.onSashStart, this); @@ -244,9 +336,26 @@ export class SplitView extends Disposable { const onChangeDisposable = onChange(this.onSashChange, this); const onEnd = Event.map(sash.onDidEnd, () => firstIndex(this.sashItems, item => item.sash === sash)); const onEndDisposable = onEnd(this.onSashEnd, this); - const onDidResetDisposable = sash.onDidReset(() => this._onDidSashReset.fire(firstIndex(this.sashItems, item => item.sash === sash))); - const disposable = combinedDisposable([onStartDisposable, onChangeDisposable, onEndDisposable, onDidResetDisposable, sash]); + const onDidResetDisposable = sash.onDidReset(() => { + const index = firstIndex(this.sashItems, item => item.sash === sash); + const upIndexes = range(index, -1); + const downIndexes = range(index + 1, this.viewItems.length); + const snapBeforeIndex = this.findFirstSnapIndex(upIndexes); + const snapAfterIndex = this.findFirstSnapIndex(downIndexes); + + if (typeof snapBeforeIndex === 'number' && !this.viewItems[snapBeforeIndex].visible) { + return; + } + + if (typeof snapAfterIndex === 'number' && !this.viewItems[snapAfterIndex].visible) { + return; + } + + this._onDidSashReset.fire(index); + }); + + const disposable = combinedDisposable(onStartDisposable, onChangeDisposable, onEndDisposable, onDidResetDisposable, sash); const sashItem: ISashItem = { sash, disposable }; this.sashItems.splice(index - 1, 0, sashItem); @@ -254,13 +363,13 @@ export class SplitView extends Disposable { container.appendChild(view.element); - let highPriorityIndex: number | undefined; + let highPriorityIndexes: number[] | undefined; if (typeof size !== 'number' && size.type === 'split') { - highPriorityIndex = size.index; + highPriorityIndexes = [size.index]; } - this.relayout(index, highPriorityIndex); + this.relayout([index], highPriorityIndexes); this.state = State.Idle; if (typeof size !== 'number' && size.type === 'distribute') { @@ -281,7 +390,7 @@ export class SplitView extends Disposable { // Remove view const viewItem = this.viewItems.splice(index, 1)[0]; - viewItem.disposable.dispose(); + const view = viewItem.dispose(); // Remove sash if (this.viewItems.length >= 1) { @@ -297,7 +406,7 @@ export class SplitView extends Disposable { this.distributeViewSizes(); } - return viewItem.view; + return view; } moveView(from: number, to: number): void { @@ -328,15 +437,34 @@ export class SplitView extends Disposable { this.addView(fromView, toSize, to); } - private relayout(lowPriorityIndex?: number, highPriorityIndex?: number): void { - const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0); - const lowPriorityIndexes = typeof lowPriorityIndex === 'number' ? [lowPriorityIndex] : undefined; - const highPriorityIndexes = typeof highPriorityIndex === 'number' ? [highPriorityIndex] : undefined; + isViewVisible(index: number): boolean { + if (index < 0 || index >= this.viewItems.length) { + throw new Error('Index out of bounds'); + } - this.resize(this.viewItems.length - 1, this.size - contentSize, undefined, lowPriorityIndexes, highPriorityIndexes); - this.distributeEmptySpace(); + const viewItem = this.viewItems[index]; + return viewItem.visible; + } + + setViewVisible(index: number, visible: boolean): void { + if (index < 0 || index >= this.viewItems.length) { + throw new Error('Index out of bounds'); + } + + const viewItem = this.viewItems[index]; + viewItem.visible = visible; + + this.distributeEmptySpace(index); this.layoutViews(); - this.saveProportions(); + } + + getViewCachedVisibleSize(index: number): number | undefined { + if (index < 0 || index >= this.viewItems.length) { + throw new Error('Index out of bounds'); + } + + const viewItem = this.viewItems[index]; + return viewItem.cachedVisibleSize; } layout(size: number): void { @@ -345,14 +473,14 @@ export class SplitView extends Disposable { if (!this.proportions) { const indexes = range(this.viewItems.length); - const lowPriorityIndexes = indexes.filter(i => this.viewItems[i].view.priority === LayoutPriority.Low); - const highPriorityIndexes = indexes.filter(i => this.viewItems[i].view.priority === LayoutPriority.High); + const lowPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.Low); + const highPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.High); this.resize(this.viewItems.length - 1, size - previousSize, undefined, lowPriorityIndexes, highPriorityIndexes); } else { for (let i = 0; i < this.viewItems.length; i++) { const item = this.viewItems[i]; - item.size = SplitView.clamp(item, Math.round(this.proportions[i] * size)); + item.size = clamp(Math.round(this.proportions[i] * size), item.minimumSize, item.maximumSize); } } @@ -370,10 +498,10 @@ export class SplitView extends Disposable { const index = firstIndex(this.sashItems, item => item.sash === sash); // This way, we can press Alt while we resize a sash, macOS style! - const disposable = combinedDisposable([ - domEvent(document.body, 'keydown')(e => resetSashDragState(this.sashDragState.current, e.altKey)), - domEvent(document.body, 'keyup')(() => resetSashDragState(this.sashDragState.current, false)) - ]); + const disposable = combinedDisposable( + domEvent(document.body, 'keydown')(e => resetSashDragState(this.sashDragState!.current, e.altKey)), + domEvent(document.body, 'keyup')(() => resetSashDragState(this.sashDragState!.current, false)) + ); const resetSashDragState = (start: number, alt: boolean) => { const sizes = this.viewItems.map(i => i.size); @@ -392,35 +520,71 @@ export class SplitView extends Disposable { if (isLastSash) { const viewItem = this.viewItems[index]; - minDelta = (viewItem.view.minimumSize - viewItem.size) / 2; - maxDelta = (viewItem.view.maximumSize - viewItem.size) / 2; + minDelta = (viewItem.minimumSize - viewItem.size) / 2; + maxDelta = (viewItem.maximumSize - viewItem.size) / 2; } else { const viewItem = this.viewItems[index + 1]; - minDelta = (viewItem.size - viewItem.view.maximumSize) / 2; - maxDelta = (viewItem.size - viewItem.view.minimumSize) / 2; + minDelta = (viewItem.size - viewItem.maximumSize) / 2; + maxDelta = (viewItem.size - viewItem.minimumSize) / 2; } } - this.sashDragState = { start, current: start, index, sizes, minDelta, maxDelta, alt, disposable }; + let snapBefore: ISashDragSnapState | undefined; + let snapAfter: ISashDragSnapState | undefined; + + if (!alt) { + const upIndexes = range(index, -1); + const downIndexes = range(index + 1, this.viewItems.length); + const minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].minimumSize - sizes[i]), 0); + const maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].viewMaximumSize - sizes[i]), 0); + const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].minimumSize), 0); + const minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].viewMaximumSize), 0); + const minDelta = Math.max(minDeltaUp, minDeltaDown); + const maxDelta = Math.min(maxDeltaDown, maxDeltaUp); + const snapBeforeIndex = this.findFirstSnapIndex(upIndexes); + const snapAfterIndex = this.findFirstSnapIndex(downIndexes); + + if (typeof snapBeforeIndex === 'number') { + const viewItem = this.viewItems[snapBeforeIndex]; + const halfSize = Math.floor(viewItem.viewMinimumSize / 2); + + snapBefore = { + index: snapBeforeIndex, + limitDelta: viewItem.visible ? minDelta - halfSize : minDelta + halfSize + }; + } + + if (typeof snapAfterIndex === 'number') { + const viewItem = this.viewItems[snapAfterIndex]; + const halfSize = Math.floor(viewItem.viewMinimumSize / 2); + + snapAfter = { + index: snapAfterIndex, + limitDelta: viewItem.visible ? maxDelta + halfSize : maxDelta - halfSize + }; + } + } + + this.sashDragState = { start, current: start, index, sizes, minDelta, maxDelta, alt, snapBefore, snapAfter, disposable }; }; resetSashDragState(start, alt); } private onSashChange({ current }: ISashEvent): void { - const { index, start, sizes, alt, minDelta, maxDelta } = this.sashDragState; - this.sashDragState.current = current; + const { index, start, sizes, alt, minDelta, maxDelta, snapBefore, snapAfter } = this.sashDragState!; + this.sashDragState!.current = current; const delta = current - start; - const newDelta = this.resize(index, delta, sizes, undefined, undefined, minDelta, maxDelta); + const newDelta = this.resize(index, delta, sizes, undefined, undefined, minDelta, maxDelta, snapBefore, snapAfter); if (alt) { const isLastSash = index === this.sashItems.length - 1; const newSizes = this.viewItems.map(i => i.size); const viewItemIndex = isLastSash ? index : index + 1; const viewItem = this.viewItems[viewItemIndex]; - const newMinDelta = viewItem.size - viewItem.view.maximumSize; - const newMaxDelta = viewItem.size - viewItem.view.minimumSize; + const newMinDelta = viewItem.size - viewItem.maximumSize; + const newMaxDelta = viewItem.size - viewItem.minimumSize; const resizeIndex = isLastSash ? index - 1 : index + 1; this.resize(resizeIndex, -newDelta, newSizes, undefined, undefined, newMinDelta, newMaxDelta); @@ -432,11 +596,11 @@ export class SplitView extends Disposable { private onSashEnd(index: number): void { this._onDidSashChange.fire(index); - this.sashDragState.disposable.dispose(); + this.sashDragState!.disposable.dispose(); this.saveProportions(); } - private onViewChange(item: IViewItem, size: number | undefined): void { + private onViewChange(item: ViewItem, size: number | undefined): void { const index = this.viewItems.indexOf(item); if (index < 0 || index >= this.viewItems.length) { @@ -444,7 +608,7 @@ export class SplitView extends Disposable { } size = typeof size === 'number' ? size : item.size; - size = SplitView.clamp(item, size); + size = clamp(size, item.minimumSize, item.maximumSize); if (this.inverseAltBehavior && index > 0) { // In this case, we want the view to grow or shrink both sides equally @@ -454,7 +618,7 @@ export class SplitView extends Disposable { this.layoutViews(); } else { item.size = size; - this.relayout(index, undefined); + this.relayout([index], undefined); } } @@ -469,42 +633,41 @@ export class SplitView extends Disposable { return; } + const indexes = range(this.viewItems.length).filter(i => i !== index); + const lowPriorityIndexes = [...indexes.filter(i => this.viewItems[i].priority === LayoutPriority.Low), index]; + const highPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.High); + const item = this.viewItems[index]; size = Math.round(size); - size = clamp(size, item.view.minimumSize, item.view.maximumSize); - let delta = size - item.size; + size = clamp(size, item.minimumSize, Math.min(item.maximumSize, this.size)); - if (delta !== 0 && index < this.viewItems.length - 1) { - const downIndexes = range(index + 1, this.viewItems.length); - const collapseDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].view.minimumSize), 0); - const expandDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - this.viewItems[i].size), 0); - const deltaDown = clamp(delta, -expandDown, collapseDown); - - this.resize(index, deltaDown); - delta -= deltaDown; - } - - if (delta !== 0 && index > 0) { - const upIndexes = range(index - 1, -1); - const collapseUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].view.minimumSize), 0); - const expandUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - this.viewItems[i].size), 0); - const deltaUp = clamp(-delta, -collapseUp, expandUp); - - this.resize(index - 1, deltaUp); - } - - this.distributeEmptySpace(); - this.layoutViews(); - this.saveProportions(); + item.size = size; + this.relayout(lowPriorityIndexes, highPriorityIndexes); this.state = State.Idle; } distributeViewSizes(): void { - const size = Math.floor(this.size / this.viewItems.length); + const flexibleViewItems: ViewItem[] = []; + let flexibleSize = 0; - for (let i = 0; i < this.viewItems.length - 1; i++) { - this.resizeView(i, size); + for (const item of this.viewItems) { + if (item.maximumSize - item.minimumSize > 0) { + flexibleViewItems.push(item); + flexibleSize += item.size; + } } + + const size = Math.floor(flexibleSize / flexibleViewItems.length); + + for (const item of flexibleViewItems) { + item.size = clamp(size, item.minimumSize, item.maximumSize); + } + + const indexes = range(this.viewItems.length); + const lowPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.Low); + const highPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.High); + + this.relayout(lowPriorityIndexes, highPriorityIndexes); } getViewSize(index: number): number { @@ -515,6 +678,15 @@ export class SplitView extends Disposable { return this.viewItems[index].size; } + private relayout(lowPriorityIndexes?: number[], highPriorityIndexes?: number[]): void { + const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0); + + this.resize(this.viewItems.length - 1, this.size - contentSize, undefined, lowPriorityIndexes, highPriorityIndexes); + this.distributeEmptySpace(); + this.layoutViews(); + this.saveProportions(); + } + private resize( index: number, delta: number, @@ -522,7 +694,9 @@ export class SplitView extends Disposable { lowPriorityIndexes?: number[], highPriorityIndexes?: number[], overloadMinDelta: number = Number.NEGATIVE_INFINITY, - overloadMaxDelta: number = Number.POSITIVE_INFINITY + overloadMaxDelta: number = Number.POSITIVE_INFINITY, + snapBefore?: ISashDragSnapState, + snapAfter?: ISashDragSnapState ): number { if (index < 0 || index >= this.viewItems.length) { return 0; @@ -551,29 +725,47 @@ export class SplitView extends Disposable { const downItems = downIndexes.map(i => this.viewItems[i]); const downSizes = downIndexes.map(i => sizes[i]); - const minDeltaUp = upIndexes.reduce((r, i) => r + ((typeof this.viewItems[i].view.snapSize === 'number' ? 0 : this.viewItems[i].view.minimumSize) - sizes[i]), 0); - const maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - sizes[i]), 0); - const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - (typeof this.viewItems[i].view.snapSize === 'number' ? 0 : this.viewItems[i].view.minimumSize)), 0); - const minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.maximumSize), 0); + const minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].minimumSize - sizes[i]), 0); + const maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].maximumSize - sizes[i]), 0); + const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].minimumSize), 0); + const minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].maximumSize), 0); const minDelta = Math.max(minDeltaUp, minDeltaDown, overloadMinDelta); const maxDelta = Math.min(maxDeltaDown, maxDeltaUp, overloadMaxDelta); - const tentativeDelta = clamp(delta, minDelta, maxDelta); - let actualDelta = 0; + let snapped = false; - for (let i = 0, deltaUp = tentativeDelta; i < upItems.length; i++) { + if (snapBefore) { + const snapView = this.viewItems[snapBefore.index]; + const visible = delta >= snapBefore.limitDelta; + snapped = visible !== snapView.visible; + snapView.visible = visible; + } + + if (!snapped && snapAfter) { + const snapView = this.viewItems[snapAfter.index]; + const visible = delta < snapAfter.limitDelta; + snapped = visible !== snapView.visible; + snapView.visible = visible; + } + + if (snapped) { + return this.resize(index, delta, sizes, lowPriorityIndexes, highPriorityIndexes, overloadMinDelta, overloadMaxDelta); + } + + delta = clamp(delta, minDelta, maxDelta); + + for (let i = 0, deltaUp = delta; i < upItems.length; i++) { const item = upItems[i]; - const size = SplitView.clamp(item, upSizes[i] + deltaUp/* , upIndexes[i] === index */); + const size = clamp(upSizes[i] + deltaUp, item.minimumSize, item.maximumSize); const viewDelta = size - upSizes[i]; - actualDelta += viewDelta; deltaUp -= viewDelta; item.size = size; } - for (let i = 0, deltaDown = actualDelta; i < downItems.length; i++) { + for (let i = 0, deltaDown = delta; i < downItems.length; i++) { const item = downItems[i]; - const size = SplitView.clamp(item, downSizes[i] - deltaDown); + const size = clamp(downSizes[i] - deltaDown, item.minimumSize, item.maximumSize); const viewDelta = size - downSizes[i]; deltaDown += viewDelta; @@ -583,24 +775,29 @@ export class SplitView extends Disposable { return delta; } - private static clamp(item: IViewItem, size: number): number { - const result = clamp(size, item.view.minimumSize, item.view.maximumSize); - - if (typeof item.view.snapSize !== 'number' || size >= item.view.minimumSize) { - return result; - } - - const snapSize = Math.min(item.view.snapSize, item.view.minimumSize); - return size < snapSize ? 0 : item.view.minimumSize; - } - - private distributeEmptySpace(): void { - let contentSize = this.viewItems.reduce((r, i) => r + i.size, 0); + private distributeEmptySpace(lowPriorityIndex?: number): void { + const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0); let emptyDelta = this.size - contentSize; - for (let i = this.viewItems.length - 1; emptyDelta !== 0 && i >= 0; i--) { - const item = this.viewItems[i]; - const size = SplitView.clamp(item, item.size + emptyDelta); + const indexes = range(this.viewItems.length - 1, -1); + const lowPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.Low); + const highPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.High); + + for (const index of highPriorityIndexes) { + pushToStart(indexes, index); + } + + for (const index of lowPriorityIndexes) { + pushToEnd(indexes, index); + } + + if (typeof lowPriorityIndex === 'number') { + pushToEnd(indexes, lowPriorityIndex); + } + + for (let i = 0; emptyDelta !== 0 && i < indexes.length; i++) { + const item = this.viewItems[indexes[i]]; + const size = clamp(item.size + emptyDelta, item.minimumSize, item.maximumSize); const viewDelta = size - item.size; emptyDelta -= viewDelta; @@ -620,31 +817,43 @@ export class SplitView extends Disposable { // Update sashes enablement let previous = false; - const collapsesDown = this.viewItems.map(i => previous = (i.size - i.view.minimumSize > 0) || previous); + const collapsesDown = this.viewItems.map(i => previous = (i.size - i.minimumSize > 0) || previous); previous = false; - const expandsDown = this.viewItems.map(i => previous = (i.view.maximumSize - i.size > 0) || previous); + const expandsDown = this.viewItems.map(i => previous = (i.maximumSize - i.size > 0) || previous); const reverseViews = [...this.viewItems].reverse(); previous = false; - const collapsesUp = reverseViews.map(i => previous = (i.size - i.view.minimumSize > 0) || previous).reverse(); + const collapsesUp = reverseViews.map(i => previous = (i.size - i.minimumSize > 0) || previous).reverse(); previous = false; - const expandsUp = reverseViews.map(i => previous = (i.view.maximumSize - i.size > 0) || previous).reverse(); + const expandsUp = reverseViews.map(i => previous = (i.maximumSize - i.size > 0) || previous).reverse(); - this.sashItems.forEach((s, i) => { - const min = !(collapsesDown[i] && expandsUp[i + 1]); - const max = !(expandsDown[i] && collapsesUp[i + 1]); + this.sashItems.forEach(({ sash }, index) => { + const min = !(collapsesDown[index] && expandsUp[index + 1]); + const max = !(expandsDown[index] && collapsesUp[index + 1]); if (min && max) { - s.sash.state = SashState.Disabled; + const upIndexes = range(index, -1); + const downIndexes = range(index + 1, this.viewItems.length); + const snapBeforeIndex = this.findFirstSnapIndex(upIndexes); + const snapAfterIndex = this.findFirstSnapIndex(downIndexes); + + if (typeof snapBeforeIndex === 'number' && !this.viewItems[snapBeforeIndex].visible) { + sash.state = SashState.Minimum; + } else if (typeof snapAfterIndex === 'number' && !this.viewItems[snapAfterIndex].visible) { + sash.state = SashState.Maximum; + } else { + sash.state = SashState.Disabled; + } } else if (min && !max) { - s.sash.state = SashState.Minimum; + sash.state = SashState.Minimum; } else if (!min && max) { - s.sash.state = SashState.Maximum; + sash.state = SashState.Maximum; } else { - s.sash.state = SashState.Enabled; + sash.state = SashState.Enabled; } + // } }); } @@ -662,10 +871,40 @@ export class SplitView extends Disposable { return 0; } + private findFirstSnapIndex(indexes: number[]): number | undefined { + // visible views first + for (const index of indexes) { + const viewItem = this.viewItems[index]; + + if (!viewItem.visible) { + continue; + } + + if (viewItem.snap) { + return index; + } + } + + // then, hidden views + for (const index of indexes) { + const viewItem = this.viewItems[index]; + + if (viewItem.visible && viewItem.maximumSize - viewItem.minimumSize > 0) { + return undefined; + } + + if (!viewItem.visible && viewItem.snap) { + return index; + } + } + + return undefined; + } + dispose(): void { super.dispose(); - this.viewItems.forEach(i => i.disposable.dispose()); + this.viewItems.forEach(i => i.dispose()); this.viewItems = []; this.sashItems.forEach(i => i.disposable.dispose()); diff --git a/src/vs/base/browser/ui/splitview/tree-collapsed-dark.svg b/src/vs/base/browser/ui/splitview/tree-collapsed-dark.svg new file mode 100644 index 00000000000..c2c2298dd5c --- /dev/null +++ b/src/vs/base/browser/ui/splitview/tree-collapsed-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/splitview/tree-collapsed-hc.svg b/src/vs/base/browser/ui/splitview/tree-collapsed-hc.svg new file mode 100644 index 00000000000..3732cbc04b8 --- /dev/null +++ b/src/vs/base/browser/ui/splitview/tree-collapsed-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/splitview/tree-collapsed-light.svg b/src/vs/base/browser/ui/splitview/tree-collapsed-light.svg new file mode 100644 index 00000000000..1952ad63f84 --- /dev/null +++ b/src/vs/base/browser/ui/splitview/tree-collapsed-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/splitview/tree-expanded-dark.svg b/src/vs/base/browser/ui/splitview/tree-expanded-dark.svg new file mode 100644 index 00000000000..5570923e175 --- /dev/null +++ b/src/vs/base/browser/ui/splitview/tree-expanded-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/splitview/tree-expanded-hc.svg b/src/vs/base/browser/ui/splitview/tree-expanded-hc.svg new file mode 100644 index 00000000000..b370009330c --- /dev/null +++ b/src/vs/base/browser/ui/splitview/tree-expanded-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/splitview/tree-expanded-light.svg b/src/vs/base/browser/ui/splitview/tree-expanded-light.svg new file mode 100644 index 00000000000..939ebc8b969 --- /dev/null +++ b/src/vs/base/browser/ui/splitview/tree-expanded-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/toolbar/ellipsis-dark.svg b/src/vs/base/browser/ui/toolbar/ellipsis-dark.svg new file mode 100644 index 00000000000..2c52e359f61 --- /dev/null +++ b/src/vs/base/browser/ui/toolbar/ellipsis-dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/vs/base/browser/ui/toolbar/ellipsis-hc.svg b/src/vs/base/browser/ui/toolbar/ellipsis-hc.svg new file mode 100644 index 00000000000..3d7068f6b4c --- /dev/null +++ b/src/vs/base/browser/ui/toolbar/ellipsis-hc.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/vs/base/browser/ui/toolbar/ellipsis-light.svg b/src/vs/base/browser/ui/toolbar/ellipsis-light.svg new file mode 100644 index 00000000000..883d2722ce3 --- /dev/null +++ b/src/vs/base/browser/ui/toolbar/ellipsis-light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/vs/base/browser/ui/toolbar/toolbar.css b/src/vs/base/browser/ui/toolbar/toolbar.css index 6738aeb68fd..47669712253 100644 --- a/src/vs/base/browser/ui/toolbar/toolbar.css +++ b/src/vs/base/browser/ui/toolbar/toolbar.css @@ -9,10 +9,13 @@ } .vs .monaco-toolbar .action-label.toolbar-toggle-more { - background-image: url('ellipsis.svg'); + background-image: url('ellipsis-light.svg'); } -.hc-black .monaco-toolbar .action-label.toolbar-toggle-more, .vs-dark .monaco-toolbar .action-label.toolbar-toggle-more { - background-image: url('ellipsis-inverse.svg'); + background-image: url('ellipsis-dark.svg'); +} + +.hc-black .monaco-toolbar .action-label.toolbar-toggle-more { + background-image: url('ellipsis-hc.svg'); } \ No newline at end of file diff --git a/src/vs/base/browser/ui/toolbar/toolbar.ts b/src/vs/base/browser/ui/toolbar/toolbar.ts index 171b8e827c7..b6329a0ce4d 100644 --- a/src/vs/base/browser/ui/toolbar/toolbar.ts +++ b/src/vs/base/browser/ui/toolbar/toolbar.ts @@ -6,19 +6,20 @@ import 'vs/css!./toolbar'; import * as nls from 'vs/nls'; import { Action, IActionRunner, IAction } from 'vs/base/common/actions'; -import { ActionBar, ActionsOrientation, IActionItemProvider } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IContextMenuProvider, DropdownMenuActionItem } from 'vs/base/browser/ui/dropdown/dropdown'; +import { ActionBar, ActionsOrientation, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar'; +import { IContextMenuProvider, DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdown'; import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; +import { withNullAsUndefined } from 'vs/base/common/types'; export const CONTEXT = 'context.toolbar'; export interface IToolBarOptions { orientation?: ActionsOrientation; - actionItemProvider?: IActionItemProvider; + actionViewItemProvider?: IActionViewItemProvider; ariaLabel?: string; - getKeyBinding?: (action: IAction) => ResolvedKeybinding; + getKeyBinding?: (action: IAction) => ResolvedKeybinding | undefined; actionRunner?: IActionRunner; toggleMenuTitle?: string; anchorAlignmentProvider?: () => AnchorAlignment; @@ -31,8 +32,8 @@ export class ToolBar extends Disposable { private options: IToolBarOptions; private actionBar: ActionBar; private toggleMenuAction: ToggleMenuAction; - private toggleMenuActionItem?: DropdownMenuActionItem; - private hasSecondaryActions: boolean; + private toggleMenuActionViewItem = this._register(new MutableDisposable()); + private hasSecondaryActions: boolean = false; private lookupKeybindings: boolean; constructor(container: HTMLElement, contextMenuProvider: IContextMenuProvider, options: IToolBarOptions = { orientation: ActionsOrientation.HORIZONTAL }) { @@ -41,7 +42,7 @@ export class ToolBar extends Disposable { this.options = options; this.lookupKeybindings = typeof this.options.getKeyBinding === 'function'; - this.toggleMenuAction = this._register(new ToggleMenuAction(() => this.toggleMenuActionItem && this.toggleMenuActionItem.show(), options.toggleMenuTitle)); + this.toggleMenuAction = this._register(new ToggleMenuAction(() => this.toggleMenuActionViewItem.value && this.toggleMenuActionViewItem.value.show(), options.toggleMenuTitle)); let element = document.createElement('div'); element.className = 'monaco-toolbar'; @@ -51,33 +52,28 @@ export class ToolBar extends Disposable { orientation: options.orientation, ariaLabel: options.ariaLabel, actionRunner: options.actionRunner, - actionItemProvider: (action: Action) => { + actionViewItemProvider: (action: Action) => { // Return special action item for the toggle menu action if (action.id === ToggleMenuAction.ID) { - // Dispose old - if (this.toggleMenuActionItem) { - this.toggleMenuActionItem.dispose(); - } - // Create new - this.toggleMenuActionItem = new DropdownMenuActionItem( + this.toggleMenuActionViewItem.value = new DropdownMenuActionViewItem( action, (action).menuActions, contextMenuProvider, - this.options.actionItemProvider, + this.options.actionViewItemProvider, this.actionRunner, this.options.getKeyBinding, 'toolbar-toggle-more', this.options.anchorAlignmentProvider ); - this.toggleMenuActionItem!.setActionContext(this.actionBar.context); + this.toggleMenuActionViewItem.value.setActionContext(this.actionBar.context); - return this.toggleMenuActionItem || null; + return this.toggleMenuActionViewItem.value; } - return options.actionItemProvider ? options.actionItemProvider(action) : null; + return options.actionViewItemProvider ? options.actionViewItemProvider(action) : undefined; } })); } @@ -92,8 +88,8 @@ export class ToolBar extends Disposable { set context(context: any) { this.actionBar.context = context; - if (this.toggleMenuActionItem) { - this.toggleMenuActionItem.setActionContext(context); + if (this.toggleMenuActionViewItem.value) { + this.toggleMenuActionViewItem.value.setActionContext(context); } } @@ -113,7 +109,7 @@ export class ToolBar extends Disposable { this.actionBar.setAriaLabel(label); } - setActions(primaryActions: IAction[], secondaryActions?: IAction[]): () => void { + setActions(primaryActions: ReadonlyArray, secondaryActions?: ReadonlyArray): () => void { return () => { let primaryActionsToSet = primaryActions ? primaryActions.slice(0) : []; @@ -135,7 +131,7 @@ export class ToolBar extends Disposable { private getKeybindingLabel(action: IAction): string | undefined { const key = this.lookupKeybindings && this.options.getKeyBinding ? this.options.getKeyBinding(action) : undefined; - return (key && key.getLabel()) || undefined; + return withNullAsUndefined(key && key.getLabel()); } addPrimaryAction(primaryAction: IAction): () => void { @@ -153,28 +149,20 @@ export class ToolBar extends Disposable { } }; } - - dispose(): void { - if (this.toggleMenuActionItem) { - this.toggleMenuActionItem.dispose(); - this.toggleMenuActionItem = undefined; - } - - super.dispose(); - } } class ToggleMenuAction extends Action { static readonly ID = 'toolbar.toggle.more'; - private _menuActions: IAction[]; + private _menuActions: ReadonlyArray; private toggleDropdownMenu: () => void; constructor(toggleDropdownMenu: () => void, title?: string) { title = title || nls.localize('moreActions', "More Actions..."); super(ToggleMenuAction.ID, title, undefined, true); + this._menuActions = []; this.toggleDropdownMenu = toggleDropdownMenu; } @@ -184,11 +172,11 @@ class ToggleMenuAction extends Action { return Promise.resolve(true); } - get menuActions() { + get menuActions(): ReadonlyArray { return this._menuActions; } - set menuActions(actions: IAction[]) { + set menuActions(actions: ReadonlyArray) { this._menuActions = actions; } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index 09cc5afa457..05f6841fd72 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -4,17 +4,124 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/tree'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { IListOptions, List, IListStyles } from 'vs/base/browser/ui/list/listWidget'; -import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent } from 'vs/base/browser/ui/list/list'; -import { append, $, toggleClass } from 'vs/base/browser/dom'; -import { Event, Relay } from 'vs/base/common/event'; -import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { IListOptions, List, IListStyles, mightProducePrintableCharacter, MouseController } from 'vs/base/browser/ui/list/listWidget'; +import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IKeyboardNavigationLabelProvider, IIdentityProvider } from 'vs/base/browser/ui/list/list'; +import { append, $, toggleClass, getDomNodePagePosition, removeClass, addClass, hasClass, hasParentWithClass, createStyleSheet, clearNode } from 'vs/base/browser/dom'; +import { Event, Relay, Emitter, EventBufferer } from 'vs/base/common/event'; +import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; -import { ITreeModel, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeFilter, ITreeNavigator, ICollapseStateChangeEvent } from 'vs/base/browser/ui/tree/tree'; +import { ITreeModel, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeFilter, ITreeNavigator, ICollapseStateChangeEvent, ITreeDragAndDrop, TreeDragOverBubble, TreeVisibility, TreeFilterResult, ITreeModelSpliceEvent, TreeMouseEventTarget } from 'vs/base/browser/ui/tree/tree'; import { ISpliceable } from 'vs/base/common/sequence'; +import { IDragAndDropData, StaticDND, DragAndDropData } from 'vs/base/browser/dnd'; +import { range, equals, distinctES6 } from 'vs/base/common/arrays'; +import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; +import { domEvent } from 'vs/base/browser/event'; +import { fuzzyScore, FuzzyScore } from 'vs/base/common/filters'; +import { getVisibleState, isFilterResult } from 'vs/base/browser/ui/tree/indexTreeModel'; +import { localize } from 'vs/nls'; +import { disposableTimeout } from 'vs/base/common/async'; +import { isMacintosh } from 'vs/base/common/platform'; +import { values } from 'vs/base/common/map'; +import { clamp } from 'vs/base/common/numbers'; +import { ScrollEvent } from 'vs/base/common/scrollable'; +import { SetMap } from 'vs/base/common/collections'; -function asListOptions(options?: IAbstractTreeOptions): IListOptions> | undefined { +function asTreeDragAndDropData(data: IDragAndDropData): IDragAndDropData { + if (data instanceof ElementsDragAndDropData) { + const nodes = (data as ElementsDragAndDropData>).elements; + return new ElementsDragAndDropData(nodes.map(node => node.element)); + } + + return data; +} + +class TreeNodeListDragAndDrop implements IListDragAndDrop> { + + private autoExpandNode: ITreeNode | undefined; + private autoExpandDisposable: IDisposable = Disposable.None; + + constructor(private modelProvider: () => ITreeModel, private dnd: ITreeDragAndDrop) { } + + getDragURI(node: ITreeNode): string | null { + return this.dnd.getDragURI(node.element); + } + + getDragLabel(nodes: ITreeNode[]): string | undefined { + if (this.dnd.getDragLabel) { + return this.dnd.getDragLabel(nodes.map(node => node.element)); + } + + return undefined; + } + + onDragStart(data: IDragAndDropData, originalEvent: DragEvent): void { + if (this.dnd.onDragStart) { + this.dnd.onDragStart(asTreeDragAndDropData(data), originalEvent); + } + } + + onDragOver(data: IDragAndDropData, targetNode: ITreeNode | undefined, targetIndex: number | undefined, originalEvent: DragEvent, raw = true): boolean | IListDragOverReaction { + const result = this.dnd.onDragOver(asTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent); + const didChangeAutoExpandNode = this.autoExpandNode !== targetNode; + + if (didChangeAutoExpandNode) { + this.autoExpandDisposable.dispose(); + this.autoExpandNode = targetNode; + } + + if (typeof targetNode === 'undefined') { + return result; + } + + if (didChangeAutoExpandNode && typeof result !== 'boolean' && result.autoExpand) { + this.autoExpandDisposable = disposableTimeout(() => { + const model = this.modelProvider(); + const ref = model.getNodeLocation(targetNode); + + if (model.isCollapsed(ref)) { + model.setCollapsed(ref, false); + } + + this.autoExpandNode = undefined; + }, 500); + } + + if (typeof result === 'boolean' || !result.accept || typeof result.bubble === 'undefined') { + if (!raw) { + const accept = typeof result === 'boolean' ? result : result.accept; + const effect = typeof result === 'boolean' ? undefined : result.effect; + return { accept, effect, feedback: [targetIndex!] }; + } + + return result; + } + + if (result.bubble === TreeDragOverBubble.Up) { + const parentNode = targetNode.parent; + const model = this.modelProvider(); + const parentIndex = parentNode && model.getListIndex(model.getNodeLocation(parentNode)); + + return this.onDragOver(data, parentNode, parentIndex, originalEvent, false); + } + + const model = this.modelProvider(); + const ref = model.getNodeLocation(targetNode); + const start = model.getListIndex(ref); + const length = model.getListRenderCount(ref); + + return { ...result, feedback: range(start, start + length) }; + } + + drop(data: IDragAndDropData, targetNode: ITreeNode | undefined, targetIndex: number | undefined, originalEvent: DragEvent): void { + this.autoExpandDisposable.dispose(); + this.autoExpandNode = undefined; + + this.dnd.drop(asTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent); + } +} + +function asListOptions(modelProvider: () => ITreeModel, options?: IAbstractTreeOptions): IListOptions> | undefined { return options && { ...options, identityProvider: options.identityProvider && { @@ -22,6 +129,7 @@ function asListOptions(options?: IAbstractTreeOptions(options?: IAbstractTreeOptions implements IListV hasDynamicHeight(element: N): boolean { return !!this.delegate.hasDynamicHeight && this.delegate.hasDynamicHeight(element.element); } + + setDynamicHeight(element: N, height: number): void { + if (this.delegate.setDynamicHeight) { + this.delegate.setDynamicHeight(element.element, height); + } + } } interface ITreeListTemplateData { - twistie: HTMLElement; - templateData: T; + readonly container: HTMLElement; + readonly indent: HTMLElement; + readonly twistie: HTMLElement; + indentGuidesDisposable: IDisposable; + readonly templateData: T; +} + +export enum RenderIndentGuides { + None = 'none', + OnHover = 'onHover', + Always = 'always' +} + +interface ITreeRendererOptions { + readonly indent?: number; + readonly renderIndentGuides?: RenderIndentGuides; +} + +interface IRenderData { + templateData: ITreeListTemplateData; + height: number; +} + +interface Collection { + readonly elements: T[]; + readonly onDidChange: Event; +} + +class EventCollection implements Collection { + + private disposables = new DisposableStore(); + + get elements(): T[] { + return this._elements; + } + + constructor(readonly onDidChange: Event, private _elements: T[] = []) { + onDidChange(e => this._elements = e, null, this.disposables); + } + + dispose() { + this.disposables.dispose(); + } } class TreeRenderer implements IListRenderer, ITreeListTemplateData> { + private static DefaultIndent = 8; + readonly templateId: string; private renderedElements = new Map>(); - private renderedNodes = new Map, ITreeListTemplateData>(); + private renderedNodes = new Map, IRenderData>(); + private indent: number = TreeRenderer.DefaultIndent; + + private _renderIndentGuides: RenderIndentGuides = RenderIndentGuides.None; + private renderedIndentGuides = new SetMap, HTMLDivElement>(); + private activeIndentNodes = new Set>(); + private indentGuidesDisposable: IDisposable = Disposable.None; + private disposables: IDisposable[] = []; constructor( private renderer: ITreeRenderer, - onDidChangeCollapseState: Event> + onDidChangeCollapseState: Event>, + private activeNodes: Collection>, + options: ITreeRendererOptions = {} ) { this.templateId = renderer.templateId; + this.updateOptions(options); Event.map(onDidChangeCollapseState, e => e.node)(this.onDidChangeNodeTwistieState, this, this.disposables); @@ -85,31 +265,70 @@ class TreeRenderer implements IListRenderer { const el = append(container, $('.monaco-tl-row')); + const indent = append(el, $('.monaco-tl-indent')); const twistie = append(el, $('.monaco-tl-twistie')); const contents = append(el, $('.monaco-tl-contents')); const templateData = this.renderer.renderTemplate(contents); - return { twistie, templateData }; + return { container, indent, twistie, indentGuidesDisposable: Disposable.None, templateData }; } - renderElement(node: ITreeNode, index: number, templateData: ITreeListTemplateData): void { - this.renderedNodes.set(node, templateData); - this.renderedElements.set(node.element, node); - - templateData.twistie.style.width = `${10 + node.depth * 10}px`; - this.renderTwistie(node, templateData.twistie); - - this.renderer.renderElement(node, index, templateData.templateData); - } - - disposeElement(node: ITreeNode, index: number, templateData: ITreeListTemplateData): void { - if (this.renderer.disposeElement) { - this.renderer.disposeElement(node, index, templateData.templateData); + renderElement(node: ITreeNode, index: number, templateData: ITreeListTemplateData, height: number | undefined): void { + if (typeof height === 'number') { + this.renderedNodes.set(node, { templateData, height }); + this.renderedElements.set(node.element, node); + } + + const indent = TreeRenderer.DefaultIndent + (node.depth - 1) * this.indent; + templateData.twistie.style.marginLeft = `${indent}px`; + templateData.indent.style.width = `${indent + this.indent - 16}px`; + + this.renderTwistie(node, templateData); + + if (typeof height === 'number') { + this.renderIndentGuides(node, templateData); + } + + this.renderer.renderElement(node, index, templateData.templateData, height); + } + + disposeElement(node: ITreeNode, index: number, templateData: ITreeListTemplateData, height: number | undefined): void { + templateData.indentGuidesDisposable.dispose(); + + if (this.renderer.disposeElement) { + this.renderer.disposeElement(node, index, templateData.templateData, height); + } + + if (typeof height === 'number') { + this.renderedNodes.delete(node); + this.renderedElements.delete(node.element); } - this.renderedNodes.delete(node); - this.renderedElements.set(node.element); } disposeTemplate(templateData: ITreeListTemplateData): void { @@ -127,27 +346,500 @@ class TreeRenderer implements IListRenderer): void { - const templateData = this.renderedNodes.get(node); + const data = this.renderedNodes.get(node); - if (!templateData) { + if (!data) { return; } - this.renderTwistie(node, templateData.twistie); + this.renderTwistie(node, data.templateData); + this._onDidChangeActiveNodes(this.activeNodes.elements); + this.renderIndentGuides(node, data.templateData); } - private renderTwistie(node: ITreeNode, twistieElement: HTMLElement) { + private renderTwistie(node: ITreeNode, templateData: ITreeListTemplateData) { if (this.renderer.renderTwistie) { - this.renderer.renderTwistie(node.element, twistieElement); + this.renderer.renderTwistie(node.element, templateData.twistie); } - toggleClass(twistieElement, 'collapsible', node.collapsible); - toggleClass(twistieElement, 'collapsed', node.collapsible && node.collapsed); + toggleClass(templateData.twistie, 'collapsible', node.collapsible); + toggleClass(templateData.twistie, 'collapsed', node.collapsible && node.collapsed); + + if (node.collapsible) { + templateData.container.setAttribute('aria-expanded', String(!node.collapsed)); + } else { + templateData.container.removeAttribute('aria-expanded'); + } + } + + private renderIndentGuides(target: ITreeNode, templateData: ITreeListTemplateData): void { + clearNode(templateData.indent); + templateData.indentGuidesDisposable.dispose(); + + if (this._renderIndentGuides === RenderIndentGuides.None) { + return; + } + + const disposableStore = new DisposableStore(); + let node = target; + + while (node.parent && node.parent.parent) { + const parent = node.parent; + const guide = $('.indent-guide', { style: `width: ${this.indent}px` }); + + if (this.activeIndentNodes.has(parent)) { + addClass(guide, 'active'); + } + + if (templateData.indent.childElementCount === 0) { + templateData.indent.appendChild(guide); + } else { + templateData.indent.insertBefore(guide, templateData.indent.firstElementChild); + } + + this.renderedIndentGuides.add(parent, guide); + disposableStore.add(toDisposable(() => this.renderedIndentGuides.delete(parent, guide))); + + node = parent; + } + + templateData.indentGuidesDisposable = disposableStore; + } + + private _onDidChangeActiveNodes(nodes: ITreeNode[]): void { + if (this._renderIndentGuides === RenderIndentGuides.None) { + return; + } + + const set = new Set>(); + + nodes.forEach(node => { + if (node.collapsible && node.children.length > 0 && !node.collapsed) { + set.add(node); + } else if (node.parent) { + set.add(node.parent); + } + }); + + this.activeIndentNodes.forEach(node => { + if (!set.has(node)) { + this.renderedIndentGuides.forEach(node, line => removeClass(line, 'active')); + } + }); + + set.forEach(node => { + if (!this.activeIndentNodes.has(node)) { + this.renderedIndentGuides.forEach(node, line => addClass(line, 'active')); + } + }); + + this.activeIndentNodes = set; } dispose(): void { this.renderedNodes.clear(); this.renderedElements.clear(); + this.indentGuidesDisposable.dispose(); + this.disposables = dispose(this.disposables); + } +} + +class TypeFilter implements ITreeFilter, IDisposable { + + private _totalCount = 0; + get totalCount(): number { return this._totalCount; } + private _matchCount = 0; + get matchCount(): number { return this._matchCount; } + + private _pattern: string = ''; + private _lowercasePattern: string = ''; + private disposables: IDisposable[] = []; + + set pattern(pattern: string) { + this._pattern = pattern; + this._lowercasePattern = pattern.toLowerCase(); + } + + constructor( + private tree: AbstractTree, + private keyboardNavigationLabelProvider: IKeyboardNavigationLabelProvider, + private _filter?: ITreeFilter + ) { + tree.onWillRefilter(this.reset, this, this.disposables); + } + + filter(element: T, parentVisibility: TreeVisibility): TreeFilterResult { + if (this._filter) { + const result = this._filter.filter(element, parentVisibility); + + if (this.tree.options.simpleKeyboardNavigation) { + return result; + } + + let visibility: TreeVisibility; + + if (typeof result === 'boolean') { + visibility = result ? TreeVisibility.Visible : TreeVisibility.Hidden; + } else if (isFilterResult(result)) { + visibility = getVisibleState(result.visibility); + } else { + visibility = result; + } + + if (visibility === TreeVisibility.Hidden) { + return false; + } + } + + this._totalCount++; + + if (this.tree.options.simpleKeyboardNavigation || !this._pattern) { + this._matchCount++; + return { data: FuzzyScore.Default, visibility: true }; + } + + const label = this.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(element); + const labelStr = label && label.toString(); + + if (typeof labelStr === 'undefined') { + return { data: FuzzyScore.Default, visibility: true }; + } + + const score = fuzzyScore(this._pattern, this._lowercasePattern, 0, labelStr, labelStr.toLowerCase(), 0, true); + + if (!score) { + if (this.tree.options.filterOnType) { + return TreeVisibility.Recurse; + } else { + return { data: FuzzyScore.Default, visibility: true }; + } + + // DEMO: smarter filter ? + // return parentVisibility === TreeVisibility.Visible ? true : TreeVisibility.Recurse; + } + + this._matchCount++; + return { data: score, visibility: true }; + } + + private reset(): void { + this._totalCount = 0; + this._matchCount = 0; + } + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} + +class TypeFilterController implements IDisposable { + + private _enabled = false; + get enabled(): boolean { return this._enabled; } + + private _pattern = ''; + get pattern(): string { return this._pattern; } + + private _filterOnType: boolean; + get filterOnType(): boolean { return this._filterOnType; } + + private _empty: boolean = false; + get empty(): boolean { return this._empty; } + + private _onDidChangeEmptyState = new Emitter(); + readonly onDidChangeEmptyState: Event = Event.latch(this._onDidChangeEmptyState.event); + + private positionClassName = 'ne'; + private domNode: HTMLElement; + private messageDomNode: HTMLElement; + private labelDomNode: HTMLElement; + private filterOnTypeDomNode: HTMLInputElement; + private clearDomNode: HTMLElement; + private keyboardNavigationEventFilter?: IKeyboardNavigationEventFilter; + + private automaticKeyboardNavigation = true; + private triggered = false; + + private _onDidChangePattern = new Emitter(); + readonly onDidChangePattern = this._onDidChangePattern.event; + + private enabledDisposables: IDisposable[] = []; + private disposables: IDisposable[] = []; + + constructor( + private tree: AbstractTree, + model: ITreeModel, + private view: List>, + private filter: TypeFilter, + private keyboardNavigationLabelProvider: IKeyboardNavigationLabelProvider + ) { + this.domNode = $(`.monaco-list-type-filter.${this.positionClassName}`); + this.domNode.draggable = true; + domEvent(this.domNode, 'dragstart')(this.onDragStart, this, this.disposables); + + this.messageDomNode = append(view.getHTMLElement(), $(`.monaco-list-type-filter-message`)); + + this.labelDomNode = append(this.domNode, $('span.label')); + const controls = append(this.domNode, $('.controls')); + + this._filterOnType = !!tree.options.filterOnType; + this.filterOnTypeDomNode = append(controls, $('input.filter')); + this.filterOnTypeDomNode.type = 'checkbox'; + this.filterOnTypeDomNode.checked = this._filterOnType; + this.filterOnTypeDomNode.tabIndex = -1; + this.updateFilterOnTypeTitle(); + domEvent(this.filterOnTypeDomNode, 'input')(this.onDidChangeFilterOnType, this, this.disposables); + + this.clearDomNode = append(controls, $('button.clear')); + this.clearDomNode.tabIndex = -1; + this.clearDomNode.title = localize('clear', "Clear"); + + this.keyboardNavigationEventFilter = tree.options.keyboardNavigationEventFilter; + + model.onDidSplice(this.onDidSpliceModel, this, this.disposables); + this.updateOptions(tree.options); + } + + updateOptions(options: IAbstractTreeOptions): void { + if (options.simpleKeyboardNavigation) { + this.disable(); + } else { + this.enable(); + } + + if (typeof options.filterOnType !== 'undefined') { + this._filterOnType = !!options.filterOnType; + this.filterOnTypeDomNode.checked = this._filterOnType; + } + + if (typeof options.automaticKeyboardNavigation !== 'undefined') { + this.automaticKeyboardNavigation = options.automaticKeyboardNavigation; + } + + this.tree.refilter(); + this.render(); + + if (!this.automaticKeyboardNavigation) { + this.onEventOrInput(''); + } + } + + toggle(): void { + this.triggered = !this.triggered; + + if (!this.triggered) { + this.onEventOrInput(''); + } + } + + private enable(): void { + if (this._enabled) { + return; + } + + const isPrintableCharEvent = this.keyboardNavigationLabelProvider.mightProducePrintableCharacter ? (e: IKeyboardEvent) => this.keyboardNavigationLabelProvider.mightProducePrintableCharacter!(e) : (e: IKeyboardEvent) => mightProducePrintableCharacter(e); + const onKeyDown = Event.chain(domEvent(this.view.getHTMLElement(), 'keydown')) + .filter(e => !isInputElement(e.target as HTMLElement) || e.target === this.filterOnTypeDomNode) + .map(e => new StandardKeyboardEvent(e)) + .filter(this.keyboardNavigationEventFilter || (() => true)) + .filter(() => this.automaticKeyboardNavigation || this.triggered) + .filter(e => isPrintableCharEvent(e) || ((this.pattern.length > 0 || this.triggered) && ((e.keyCode === KeyCode.Escape || e.keyCode === KeyCode.Backspace) && !e.altKey && !e.ctrlKey && !e.metaKey) || (e.keyCode === KeyCode.Backspace && (isMacintosh ? (e.altKey && !e.metaKey) : e.ctrlKey) && !e.shiftKey))) + .forEach(e => { e.stopPropagation(); e.preventDefault(); }) + .event; + + const onClear = domEvent(this.clearDomNode, 'click'); + + Event.chain(Event.any(onKeyDown, onClear)) + .event(this.onEventOrInput, this, this.enabledDisposables); + + this.filter.pattern = ''; + this.tree.refilter(); + this.render(); + this._enabled = true; + this.triggered = false; + } + + private disable(): void { + if (!this._enabled) { + return; + } + + this.domNode.remove(); + this.enabledDisposables = dispose(this.enabledDisposables); + this.tree.refilter(); + this.render(); + this._enabled = false; + this.triggered = false; + } + + private onEventOrInput(e: MouseEvent | StandardKeyboardEvent | string): void { + if (typeof e === 'string') { + this.onInput(e); + } else if (e instanceof MouseEvent || e.keyCode === KeyCode.Escape || (e.keyCode === KeyCode.Backspace && (isMacintosh ? e.altKey : e.ctrlKey))) { + this.onInput(''); + } else if (e.keyCode === KeyCode.Backspace) { + this.onInput(this.pattern.length === 0 ? '' : this.pattern.substr(0, this.pattern.length - 1)); + } else { + this.onInput(this.pattern + e.browserEvent.key); + } + } + + private onInput(pattern: string): void { + const container = this.view.getHTMLElement(); + + if (pattern && !this.domNode.parentElement) { + container.append(this.domNode); + } else if (!pattern && this.domNode.parentElement) { + this.domNode.remove(); + this.tree.domFocus(); + } + + this._pattern = pattern; + this._onDidChangePattern.fire(pattern); + + this.filter.pattern = pattern; + this.tree.refilter(); + + if (pattern) { + this.tree.focusNext(0, true, undefined, node => !FuzzyScore.isDefault(node.filterData as any as FuzzyScore)); + } + + const focus = this.tree.getFocus(); + + if (focus.length > 0) { + const element = focus[0]; + + if (this.tree.getRelativeTop(element) === null) { + this.tree.reveal(element, 0.5); + } + } + + this.render(); + + if (!pattern) { + this.triggered = false; + } + } + + private onDragStart(): void { + const container = this.view.getHTMLElement(); + const { left } = getDomNodePagePosition(container); + const containerWidth = container.clientWidth; + const midContainerWidth = containerWidth / 2; + const width = this.domNode.clientWidth; + const disposables: IDisposable[] = []; + let positionClassName = this.positionClassName; + + const updatePosition = () => { + switch (positionClassName) { + case 'nw': + this.domNode.style.top = `4px`; + this.domNode.style.left = `4px`; + break; + case 'ne': + this.domNode.style.top = `4px`; + this.domNode.style.left = `${containerWidth - width - 6}px`; + break; + } + }; + + const onDragOver = (event: DragEvent) => { + event.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome) + + const x = event.screenX - left; + if (event.dataTransfer) { + event.dataTransfer.dropEffect = 'none'; + } + + if (x < midContainerWidth) { + positionClassName = 'nw'; + } else { + positionClassName = 'ne'; + } + + updatePosition(); + }; + + const onDragEnd = () => { + this.positionClassName = positionClassName; + this.domNode.className = `monaco-list-type-filter ${this.positionClassName}`; + this.domNode.style.top = null; + this.domNode.style.left = null; + + dispose(disposables); + }; + + updatePosition(); + removeClass(this.domNode, positionClassName); + + addClass(this.domNode, 'dragging'); + disposables.push(toDisposable(() => removeClass(this.domNode, 'dragging'))); + + domEvent(document, 'dragover')(onDragOver, null, disposables); + domEvent(this.domNode, 'dragend')(onDragEnd, null, disposables); + + StaticDND.CurrentDragAndDropData = new DragAndDropData('vscode-ui'); + disposables.push(toDisposable(() => StaticDND.CurrentDragAndDropData = undefined)); + } + + private onDidSpliceModel(): void { + if (!this._enabled || this.pattern.length === 0) { + return; + } + + this.tree.refilter(); + this.render(); + } + + private onDidChangeFilterOnType(): void { + this.tree.updateOptions({ filterOnType: this.filterOnTypeDomNode.checked }); + this.tree.refilter(); + this.tree.domFocus(); + this.render(); + this.updateFilterOnTypeTitle(); + } + + private updateFilterOnTypeTitle(): void { + if (this.filterOnType) { + this.filterOnTypeDomNode.title = localize('disable filter on type', "Disable Filter on Type"); + } else { + this.filterOnTypeDomNode.title = localize('enable filter on type', "Enable Filter on Type"); + } + } + + private render(): void { + const noMatches = this.filter.totalCount > 0 && this.filter.matchCount === 0; + + if (this.pattern && this.tree.options.filterOnType && noMatches) { + this.messageDomNode.textContent = localize('empty', "No elements found"); + this._empty = true; + } else { + this.messageDomNode.innerHTML = ''; + this._empty = false; + } + + toggleClass(this.domNode, 'no-matches', noMatches); + this.domNode.title = localize('found', "Matched {0} out of {1} elements", this.filter.matchCount, this.filter.totalCount); + this.labelDomNode.textContent = this.pattern.length > 16 ? '…' + this.pattern.substr(this.pattern.length - 16) : this.pattern; + + this._onDidChangeEmptyState.fire(this._empty); + } + + shouldAllowFocus(node: ITreeNode): boolean { + if (!this.enabled || !this.pattern || this.filterOnType) { + return true; + } + + if (this.filter.totalCount > 0 && this.filter.matchCount <= 1) { + return true; + } + + return !FuzzyScore.isDefault(node.filterData as any as FuzzyScore); + } + + dispose() { + this.disable(); + this._onDidChangePattern.dispose(); this.disposables = dispose(this.disposables); } } @@ -164,9 +856,18 @@ function asTreeEvent(event: IListEvent>): ITreeEvent { } function asTreeMouseEvent(event: IListMouseEvent>): ITreeMouseEvent { + let target: TreeMouseEventTarget = TreeMouseEventTarget.Unknown; + + if (hasParentWithClass(event.browserEvent.target as HTMLElement, 'monaco-tl-twistie', 'monaco-tl-row')) { + target = TreeMouseEventTarget.Twistie; + } else if (hasParentWithClass(event.browserEvent.target as HTMLElement, 'monaco-tl-contents', 'monaco-tl-row')) { + target = TreeMouseEventTarget.Element; + } + return { browserEvent: event.browserEvent, - element: event.element ? event.element.element : null + element: event.element ? event.element.element : null, + target }; } @@ -178,19 +879,280 @@ function asTreeContextMenuEvent(event: IListContextMenuEvent extends IListOptions { - collapseByDefault?: boolean; // defaults to false - filter?: ITreeFilter; +export interface IKeyboardNavigationEventFilter { + (e: StandardKeyboardEvent): boolean; +} + +export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions { + readonly automaticKeyboardNavigation?: boolean; + readonly simpleKeyboardNavigation?: boolean; + readonly filterOnType?: boolean; + readonly openOnSingleClick?: boolean; +} + +export interface IAbstractTreeOptions extends IAbstractTreeOptionsUpdate, IListOptions { + readonly collapseByDefault?: boolean; // defaults to false + readonly filter?: ITreeFilter; + readonly dnd?: ITreeDragAndDrop; + readonly autoExpandSingleChildren?: boolean; + readonly keyboardNavigationEventFilter?: IKeyboardNavigationEventFilter; + readonly expandOnlyOnTwistieClick?: boolean | ((e: T) => boolean); +} + +function dfs(node: ITreeNode, fn: (node: ITreeNode) => void): void { + fn(node); + node.children.forEach(child => dfs(child, fn)); +} + +/** + * The trait concept needs to exist at the tree level, because collapsed + * tree nodes will not be known by the list. + */ +class Trait { + + private nodes: ITreeNode[] = []; + private elements: T[] | undefined; + + private _onDidChange = new Emitter>(); + readonly onDidChange = this._onDidChange.event; + + private _nodeSet: Set> | undefined; + private get nodeSet(): Set> { + if (!this._nodeSet) { + this._nodeSet = this.createNodeSet(); + } + + return this._nodeSet; + } + + constructor(private identityProvider?: IIdentityProvider) { } + + set(nodes: ITreeNode[], browserEvent?: UIEvent): void { + if (equals(this.nodes, nodes)) { + return; + } + + this._set(nodes, false, browserEvent); + } + + private _set(nodes: ITreeNode[], silent: boolean, browserEvent?: UIEvent): void { + this.nodes = [...nodes]; + this.elements = undefined; + this._nodeSet = undefined; + + if (!silent) { + const that = this; + this._onDidChange.fire({ get elements() { return that.get(); }, browserEvent }); + } + } + + get(): T[] { + if (!this.elements) { + this.elements = this.nodes.map(node => node.element); + } + + return [...this.elements]; + } + + getNodes(): readonly ITreeNode[] { + return this.nodes; + } + + has(node: ITreeNode): boolean { + return this.nodeSet.has(node); + } + + onDidModelSplice({ insertedNodes, deletedNodes }: ITreeModelSpliceEvent): void { + if (!this.identityProvider) { + const set = this.createNodeSet(); + const visit = (node: ITreeNode) => set.delete(node); + deletedNodes.forEach(node => dfs(node, visit)); + this.set(values(set)); + return; + } + + const deletedNodesIdSet = new Set(); + const deletedNodesVisitor = (node: ITreeNode) => deletedNodesIdSet.add(this.identityProvider!.getId(node.element).toString()); + deletedNodes.forEach(node => dfs(node, deletedNodesVisitor)); + + const insertedNodesMap = new Map>(); + const insertedNodesVisitor = (node: ITreeNode) => insertedNodesMap.set(this.identityProvider!.getId(node.element).toString(), node); + insertedNodes.forEach(node => dfs(node, insertedNodesVisitor)); + + const nodes: ITreeNode[] = []; + let silent = true; + + for (const node of this.nodes) { + const id = this.identityProvider.getId(node.element).toString(); + const wasDeleted = deletedNodesIdSet.has(id); + + if (!wasDeleted) { + nodes.push(node); + } else { + const insertedNode = insertedNodesMap.get(id); + + if (insertedNode) { + nodes.push(insertedNode); + } else { + silent = false; + } + } + } + + this._set(nodes, silent); + } + + private createNodeSet(): Set> { + const set = new Set>(); + + for (const node of this.nodes) { + set.add(node); + } + + return set; + } +} + +class TreeNodeListMouseController extends MouseController> { + + constructor(list: TreeNodeList, private tree: AbstractTree) { + super(list); + } + + protected onPointer(e: IListMouseEvent>): void { + if (isInputElement(e.browserEvent.target as HTMLElement)) { + return; + } + + const node = e.element; + + if (!node) { + return super.onPointer(e); + } + + if (this.isSelectionRangeChangeEvent(e) || this.isSelectionSingleChangeEvent(e)) { + return super.onPointer(e); + } + + const onTwistie = hasClass(e.browserEvent.target as HTMLElement, 'monaco-tl-twistie'); + + if (!this.tree.openOnSingleClick && e.browserEvent.detail !== 2 && !onTwistie) { + return super.onPointer(e); + } + + let expandOnlyOnTwistieClick = false; + + if (typeof this.tree.expandOnlyOnTwistieClick === 'function') { + expandOnlyOnTwistieClick = this.tree.expandOnlyOnTwistieClick(node.element); + } else { + expandOnlyOnTwistieClick = !!this.tree.expandOnlyOnTwistieClick; + } + + if (expandOnlyOnTwistieClick && !onTwistie) { + return super.onPointer(e); + } + + const model = ((this.tree as any).model as ITreeModel); // internal + const location = model.getNodeLocation(node); + const recursive = e.browserEvent.altKey; + model.setCollapsed(location, undefined, recursive); + + if (expandOnlyOnTwistieClick && onTwistie) { + return; + } + + super.onPointer(e); + } +} + +interface ITreeNodeListOptions extends IListOptions> { + readonly tree: AbstractTree; +} + +/** + * We use this List subclass to restore selection and focus as nodes + * get rendered in the list, possibly due to a node expand() call. + */ +class TreeNodeList extends List> { + + constructor( + container: HTMLElement, + virtualDelegate: IListVirtualDelegate>, + renderers: IListRenderer[], + private focusTrait: Trait, + private selectionTrait: Trait, + options: ITreeNodeListOptions + ) { + super(container, virtualDelegate, renderers, options); + } + + protected createMouseController(options: ITreeNodeListOptions): MouseController> { + return new TreeNodeListMouseController(this, options.tree); + } + + splice(start: number, deleteCount: number, elements: ITreeNode[] = []): void { + super.splice(start, deleteCount, elements); + + if (elements.length === 0) { + return; + } + + const additionalFocus: number[] = []; + const additionalSelection: number[] = []; + + elements.forEach((node, index) => { + if (this.focusTrait.has(node)) { + additionalFocus.push(start + index); + } + + if (this.selectionTrait.has(node)) { + additionalSelection.push(start + index); + } + }); + + if (additionalFocus.length > 0) { + super.setFocus(distinctES6([...super.getFocus(), ...additionalFocus])); + } + + if (additionalSelection.length > 0) { + super.setSelection(distinctES6([...super.getSelection(), ...additionalSelection])); + } + } + + setFocus(indexes: number[], browserEvent?: UIEvent, fromAPI = false): void { + super.setFocus(indexes, browserEvent); + + if (!fromAPI) { + this.focusTrait.set(indexes.map(i => this.element(i)), browserEvent); + } + } + + setSelection(indexes: number[], browserEvent?: UIEvent, fromAPI = false): void { + super.setSelection(indexes, browserEvent); + + if (!fromAPI) { + this.selectionTrait.set(indexes.map(i => this.element(i)), browserEvent); + } + } } export abstract class AbstractTree implements IDisposable { - private view: List>; + protected view: TreeNodeList; + private renderers: TreeRenderer[]; protected model: ITreeModel; + private focus: Trait; + private selection: Trait; + private eventBufferer = new EventBufferer(); + private typeFilterController?: TypeFilterController; + private focusNavigationFilter: ((node: ITreeNode) => boolean) | undefined; + private styleElement: HTMLStyleElement; protected disposables: IDisposable[] = []; - get onDidChangeFocus(): Event> { return Event.map(this.view.onFocusChange, asTreeEvent); } - get onDidChangeSelection(): Event> { return Event.map(this.view.onSelectionChange, asTreeEvent); } + get onDidScroll(): Event { return this.view.onDidScroll; } + + get onDidChangeFocus(): Event> { return this.eventBufferer.wrapEvent(this.focus.onDidChange); } + get onDidChangeSelection(): Event> { return this.eventBufferer.wrapEvent(this.selection.onDidChange); } get onDidOpen(): Event> { return Event.map(this.view.onDidOpen, asTreeEvent); } get onMouseClick(): Event> { return Event.map(this.view.onMouseClick, asTreeMouseEvent); } @@ -207,28 +1169,59 @@ export abstract class AbstractTree implements IDisposable get onDidChangeCollapseState(): Event> { return this.model.onDidChangeCollapseState; } get onDidChangeRenderNodeCount(): Event> { return this.model.onDidChangeRenderNodeCount; } + private _onWillRefilter = new Emitter(); + readonly onWillRefilter: Event = this._onWillRefilter.event; + + get filterOnType(): boolean { return !!this._options.filterOnType; } + get onDidChangeTypeFilterPattern(): Event { return this.typeFilterController ? this.typeFilterController.onDidChangePattern : Event.None; } + + get openOnSingleClick(): boolean { return typeof this._options.openOnSingleClick === 'undefined' ? true : this._options.openOnSingleClick; } + get expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? false : this._options.expandOnlyOnTwistieClick; } + + private _onDidUpdateOptions = new Emitter>(); + readonly onDidUpdateOptions: Event> = this._onDidUpdateOptions.event; + get onDidDispose(): Event { return this.view.onDidDispose; } constructor( container: HTMLElement, delegate: IListVirtualDelegate, - renderers: ITreeRenderer[], - options: IAbstractTreeOptions = {} + renderers: ITreeRenderer[], + private _options: IAbstractTreeOptions = {} ) { const treeDelegate = new ComposedTreeDelegate>(delegate); const onDidChangeCollapseStateRelay = new Relay>(); - const treeRenderers = renderers.map(r => new TreeRenderer(r, onDidChangeCollapseStateRelay.event)); - this.disposables.push(...treeRenderers); + const onDidChangeActiveNodes = new Relay[]>(); + const activeNodes = new EventCollection(onDidChangeActiveNodes.event); + this.disposables.push(activeNodes); - this.view = new List(container, treeDelegate, treeRenderers, asListOptions(options)); + this.renderers = renderers.map(r => new TreeRenderer(r, onDidChangeCollapseStateRelay.event, activeNodes, _options)); + this.disposables.push(...this.renderers); - this.model = this.createModel(this.view, options); + let filter: TypeFilter | undefined; + + if (_options.keyboardNavigationLabelProvider) { + filter = new TypeFilter(this, _options.keyboardNavigationLabelProvider, _options.filter as any as ITreeFilter); + _options = { ..._options, filter: filter as ITreeFilter }; // TODO need typescript help here + this.disposables.push(filter); + } + + this.focus = new Trait(_options.identityProvider); + this.selection = new Trait(_options.identityProvider); + this.view = new TreeNodeList(container, treeDelegate, this.renderers, this.focus, this.selection, { ...asListOptions(() => this.model, _options), tree: this }); + + this.model = this.createModel(this.view, _options); onDidChangeCollapseStateRelay.input = this.model.onDidChangeCollapseState; - this.view.onMouseClick(this.reactOnMouseClick, this, this.disposables); + this.model.onDidSplice(e => { + this.focus.onDidModelSplice(e); + this.selection.onDidModelSplice(e); + }, null, this.disposables); - if (options.keyboardSupport !== false) { + onDidChangeActiveNodes.input = Event.map(Event.any(this.focus.onDidChange, this.selection.onDidChange, this.model.onDidSplice), () => [...this.focus.getNodes(), ...this.selection.getNodes()]); + + if (_options.keyboardSupport !== false) { const onKeyDown = Event.chain(this.view.onKeyDown) .filter(e => !isInputElement(e.target as HTMLElement)) .map(e => new StandardKeyboardEvent(e)); @@ -237,6 +1230,50 @@ export abstract class AbstractTree implements IDisposable onKeyDown.filter(e => e.keyCode === KeyCode.RightArrow).on(this.onRightArrow, this, this.disposables); onKeyDown.filter(e => e.keyCode === KeyCode.Space).on(this.onSpace, this, this.disposables); } + + if (_options.keyboardNavigationLabelProvider) { + this.typeFilterController = new TypeFilterController(this, this.model, this.view, filter!, _options.keyboardNavigationLabelProvider); + this.focusNavigationFilter = node => this.typeFilterController!.shouldAllowFocus(node); + this.disposables.push(this.typeFilterController!); + } + + this.styleElement = createStyleSheet(this.view.getHTMLElement()); + toggleClass(this.getHTMLElement(), 'always', this._options.renderIndentGuides === RenderIndentGuides.Always); + } + + updateOptions(optionsUpdate: IAbstractTreeOptionsUpdate = {}): void { + this._options = { ...this._options, ...optionsUpdate }; + + for (const renderer of this.renderers) { + renderer.updateOptions(optionsUpdate); + } + + this.view.updateOptions({ + enableKeyboardNavigation: this._options.simpleKeyboardNavigation, + automaticKeyboardNavigation: this._options.automaticKeyboardNavigation + }); + + if (this.typeFilterController) { + this.typeFilterController.updateOptions(this._options); + } + + this._onDidUpdateOptions.fire(this._options); + + toggleClass(this.getHTMLElement(), 'always', this._options.renderIndentGuides === RenderIndentGuides.Always); + } + + get options(): IAbstractTreeOptions { + return this._options; + } + + updateWidth(element: TRef): void { + const index = this.model.getListIndex(element); + + if (index === -1) { + return; + } + + this.view.updateWidth(index); } // Widget @@ -246,11 +1283,21 @@ export abstract class AbstractTree implements IDisposable } get contentHeight(): number { + if (this.typeFilterController && this.typeFilterController.filterOnType && this.typeFilterController.empty) { + return 100; + } + return this.view.contentHeight; } get onDidChangeContentHeight(): Event { - return this.view.onDidChangeContentHeight; + let result = this.view.onDidChangeContentHeight; + + if (this.typeFilterController) { + result = Event.any(result, Event.map(this.typeFilterController.onDidChangeEmptyState, () => this.contentHeight)); + } + + return result; } get scrollTop(): number { @@ -269,6 +1316,18 @@ export abstract class AbstractTree implements IDisposable return this.view.renderHeight; } + get firstVisibleElement(): T { + const index = this.view.firstVisibleIndex; + const node = this.view.element(index); + return node.element; + } + + get lastVisibleElement(): T { + const index = this.view.lastVisibleIndex; + const node = this.view.element(index); + return node.element; + } + domFocus(): void { this.view.domFocus(); } @@ -277,15 +1336,24 @@ export abstract class AbstractTree implements IDisposable return this.getHTMLElement() === document.activeElement; } - layout(height?: number): void { - this.view.layout(height); - } - - layoutWidth(width: number): void { - this.view.layoutWidth(width); + layout(height?: number, width?: number): void { + this.view.layout(height, width); } style(styles: IListStyles): void { + const suffix = `.${this.view.domId}`; + const content: string[] = []; + + if (styles.treeIndentGuidesStroke) { + content.push(`.monaco-list${suffix}:hover .monaco-tl-indent > .indent-guide, .monaco-list${suffix}.always .monaco-tl-indent > .indent-guide { border-color: ${styles.treeIndentGuidesStroke.transparent(0.4)}; }`); + content.push(`.monaco-list${suffix} .monaco-tl-indent > .indent-guide.active { border-color: ${styles.treeIndentGuidesStroke}; }`); + } + + const newStyles = content.join('\n'); + if (newStyles !== this.styleElement.innerHTML) { + this.styleElement.innerHTML = newStyles; + } + this.view.style(styles); } @@ -299,10 +1367,6 @@ export abstract class AbstractTree implements IDisposable return this.model.getFirstElementChild(location); } - getLastElementAncestor(location?: TRef): T | undefined { - return this.model.getLastElementAncestor(location); - } - // Tree getNode(location?: TRef): ITreeNode { @@ -337,61 +1401,81 @@ export abstract class AbstractTree implements IDisposable return this.model.isCollapsed(location); } + toggleKeyboardNavigation(): void { + this.view.toggleKeyboardNavigation(); + + if (this.typeFilterController) { + this.typeFilterController.toggle(); + } + } + refilter(): void { + this._onWillRefilter.fire(undefined); this.model.refilter(); } setSelection(elements: TRef[], browserEvent?: UIEvent): void { - const indexes = elements.map(e => this.model.getListIndex(e)); - this.view.setSelection(indexes, browserEvent); + const nodes = elements.map(e => this.model.getNode(e)); + this.selection.set(nodes, browserEvent); + + const indexes = elements.map(e => this.model.getListIndex(e)).filter(i => i > -1); + this.view.setSelection(indexes, browserEvent, true); } getSelection(): T[] { - const nodes = this.view.getSelectedElements(); - return nodes.map(n => n.element); + return this.selection.get(); } setFocus(elements: TRef[], browserEvent?: UIEvent): void { - const indexes = elements.map(e => this.model.getListIndex(e)); - this.view.setFocus(indexes, browserEvent); + const nodes = elements.map(e => this.model.getNode(e)); + this.focus.set(nodes, browserEvent); + + const indexes = elements.map(e => this.model.getListIndex(e)).filter(i => i > -1); + this.view.setFocus(indexes, browserEvent, true); } - focusNext(n = 1, loop = false, browserEvent?: UIEvent): void { - this.view.focusNext(n, loop, browserEvent); + focusNext(n = 1, loop = false, browserEvent?: UIEvent, filter = this.focusNavigationFilter): void { + this.view.focusNext(n, loop, browserEvent, filter); } - focusPrevious(n = 1, loop = false, browserEvent?: UIEvent): void { - this.view.focusPrevious(n, loop, browserEvent); + focusPrevious(n = 1, loop = false, browserEvent?: UIEvent, filter = this.focusNavigationFilter): void { + this.view.focusPrevious(n, loop, browserEvent, filter); } - focusNextPage(browserEvent?: UIEvent): void { - this.view.focusNextPage(browserEvent); + focusNextPage(browserEvent?: UIEvent, filter = this.focusNavigationFilter): void { + this.view.focusNextPage(browserEvent, filter); } - focusPreviousPage(browserEvent?: UIEvent): void { - this.view.focusPreviousPage(browserEvent); + focusPreviousPage(browserEvent?: UIEvent, filter = this.focusNavigationFilter): void { + this.view.focusPreviousPage(browserEvent, filter); } - focusLast(browserEvent?: UIEvent): void { - this.view.focusLast(browserEvent); + focusLast(browserEvent?: UIEvent, filter = this.focusNavigationFilter): void { + this.view.focusLast(browserEvent, filter); } - focusFirst(browserEvent?: UIEvent): void { - this.view.focusFirst(browserEvent); + focusFirst(browserEvent?: UIEvent, filter = this.focusNavigationFilter): void { + this.view.focusFirst(browserEvent, filter); } getFocus(): T[] { - const nodes = this.view.getFocusedElements(); - return nodes.map(n => n.element); + return this.focus.get(); } - open(elements: TRef[]): void { + open(elements: TRef[], browserEvent?: UIEvent): void { const indexes = elements.map(e => this.model.getListIndex(e)); - this.view.open(indexes); + this.view.open(indexes, browserEvent); } reveal(location: TRef, relativeTop?: number): void { + this.model.expandTo(location); + const index = this.model.getListIndex(location); + + if (index === -1) { + return; + } + this.view.reveal(index, relativeTop); } @@ -401,28 +1485,16 @@ export abstract class AbstractTree implements IDisposable */ getRelativeTop(location: TRef): number | null { const index = this.model.getListIndex(location); + + if (index === -1) { + return null; + } + return this.view.getRelativeTop(index); } // List - get visibleNodeCount(): number { - return this.view.length; - } - - private reactOnMouseClick(e: IListMouseEvent>): void { - const node = e.element; - - if (!node) { - return; - } - - const location = this.model.getNodeLocation(node); - const recursive = e.browserEvent.altKey; - - this.model.setCollapsed(location, undefined, recursive); - } - private onLeftArrow(e: StandardKeyboardEvent): void { e.preventDefault(); e.stopPropagation(); @@ -466,7 +1538,7 @@ export abstract class AbstractTree implements IDisposable const didChange = this.model.setCollapsed(location, false); if (!didChange) { - if (node.children.length === 0) { + if (!node.children.some(child => child.visible)) { return; } @@ -567,4 +1639,4 @@ class TreeNavigator, TFilterData, TRef> implements IT this.index = this.view.length - 1; return this.current(); } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/tree/asyncDataTree.ts b/src/vs/base/browser/ui/tree/asyncDataTree.ts index b0970cb21bb..385cd3556de 100644 --- a/src/vs/base/browser/ui/tree/asyncDataTree.ts +++ b/src/vs/base/browser/ui/tree/asyncDataTree.ts @@ -3,30 +3,63 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ComposedTreeDelegate, IAbstractTreeOptions } from 'vs/base/browser/ui/tree/abstractTree'; +import { ComposedTreeDelegate, IAbstractTreeOptions, IAbstractTreeOptionsUpdate } from 'vs/base/browser/ui/tree/abstractTree'; import { ObjectTree, IObjectTreeOptions } from 'vs/base/browser/ui/tree/objectTree'; -import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list'; -import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree'; +import { IListVirtualDelegate, IIdentityProvider, IListDragAndDrop, IListDragOverReaction } from 'vs/base/browser/ui/list/list'; +import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent, IAsyncDataSource, ITreeDragAndDrop } from 'vs/base/browser/ui/tree/tree'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; -import { timeout, always } from 'vs/base/common/async'; +import { timeout, CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; import { IListStyles } from 'vs/base/browser/ui/list/listWidget'; -import { toggleClass } from 'vs/base/browser/dom'; import { Iterator } from 'vs/base/common/iterator'; - -enum AsyncDataTreeNodeState { - Uninitialized, - Loaded, - Loading, - Slow -} +import { IDragAndDropData } from 'vs/base/browser/dnd'; +import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; +import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors'; +import { toggleClass } from 'vs/base/browser/dom'; +import { values } from 'vs/base/common/map'; +import { ScrollEvent } from 'vs/base/common/scrollable'; interface IAsyncDataTreeNode { element: TInput | T; readonly parent: IAsyncDataTreeNode | null; + readonly children: IAsyncDataTreeNode[]; readonly id?: string | null; - readonly children?: IAsyncDataTreeNode[]; - state: AsyncDataTreeNodeState; + loading: boolean; + hasChildren: boolean; + stale: boolean; + slow: boolean; + collapsedByDefault: boolean | undefined; +} + +interface IAsyncDataTreeNodeRequiredProps extends Partial> { + readonly element: TInput | T; + readonly parent: IAsyncDataTreeNode | null; + readonly hasChildren: boolean; +} + +function createAsyncDataTreeNode(props: IAsyncDataTreeNodeRequiredProps): IAsyncDataTreeNode { + return { + ...props, + children: [], + loading: false, + stale: true, + slow: false, + collapsedByDefault: undefined + }; +} + +function isAncestor(ancestor: IAsyncDataTreeNode, descendant: IAsyncDataTreeNode): boolean { + if (!descendant.parent) { + return false; + } else if (descendant.parent === ancestor) { + return true; + } else { + return isAncestor(ancestor, descendant.parent); + } +} + +function intersects(node: IAsyncDataTreeNode, other: IAsyncDataTreeNode): boolean { + return node === other || isAncestor(node, other) || isAncestor(other, node); } interface IDataTreeListTemplateData { @@ -39,6 +72,8 @@ class AsyncDataTreeNodeWrapper implements ITreeNode | undefined { return this.node.parent && new AsyncDataTreeNodeWrapper(this.node.parent); } get children(): ITreeNode[] { return this.node.children.map(node => new AsyncDataTreeNodeWrapper(node)); } get depth(): number { return this.node.depth; } + get visibleChildrenCount(): number { return this.node.visibleChildrenCount; } + get visibleChildIndex(): number { return this.node.visibleChildIndex; } get collapsible(): boolean { return this.node.collapsible; } get collapsed(): boolean { return this.node.collapsed; } get visible(): boolean { return this.node.visible; } @@ -65,18 +100,18 @@ class DataTreeRenderer implements ITreeRe return { templateData }; } - renderElement(node: ITreeNode, TFilterData>, index: number, templateData: IDataTreeListTemplateData): void { - this.renderer.renderElement(new AsyncDataTreeNodeWrapper(node), index, templateData.templateData); + renderElement(node: ITreeNode, TFilterData>, index: number, templateData: IDataTreeListTemplateData, height: number | undefined): void { + this.renderer.renderElement(new AsyncDataTreeNodeWrapper(node), index, templateData.templateData, height); } renderTwistie(element: IAsyncDataTreeNode, twistieElement: HTMLElement): boolean { - toggleClass(twistieElement, 'loading', element.state === AsyncDataTreeNodeState.Slow); + toggleClass(twistieElement, 'loading', element.slow); return false; } - disposeElement(node: ITreeNode, TFilterData>, index: number, templateData: IDataTreeListTemplateData): void { + disposeElement(node: ITreeNode, TFilterData>, index: number, templateData: IDataTreeListTemplateData, height: number | undefined): void { if (this.renderer.disposeElement) { - this.renderer.disposeElement(new AsyncDataTreeNodeWrapper(node), index, templateData.templateData); + this.renderer.disposeElement(new AsyncDataTreeNodeWrapper(node), index, templateData.templateData, height); } } @@ -100,7 +135,8 @@ function asTreeEvent(e: ITreeEvent>): I function asTreeMouseEvent(e: ITreeMouseEvent>): ITreeMouseEvent { return { browserEvent: e.browserEvent, - element: e.element && e.element.element as T + element: e.element && e.element.element as T, + target: e.target }; } @@ -122,14 +158,56 @@ export interface IChildrenResolutionEvent { readonly reason: ChildrenResolutionReason; } +function asAsyncDataTreeDragAndDropData(data: IDragAndDropData): IDragAndDropData { + if (data instanceof ElementsDragAndDropData) { + const nodes = (data as ElementsDragAndDropData>).elements; + return new ElementsDragAndDropData(nodes.map(node => node.element)); + } + + return data; +} + +class AsyncDataTreeNodeListDragAndDrop implements IListDragAndDrop> { + + constructor(private dnd: ITreeDragAndDrop) { } + + getDragURI(node: IAsyncDataTreeNode): string | null { + return this.dnd.getDragURI(node.element as T); + } + + getDragLabel(nodes: IAsyncDataTreeNode[]): string | undefined { + if (this.dnd.getDragLabel) { + return this.dnd.getDragLabel(nodes.map(node => node.element as T)); + } + + return undefined; + } + + onDragStart(data: IDragAndDropData, originalEvent: DragEvent): void { + if (this.dnd.onDragStart) { + this.dnd.onDragStart(asAsyncDataTreeDragAndDropData(data), originalEvent); + } + } + + onDragOver(data: IDragAndDropData, targetNode: IAsyncDataTreeNode | undefined, targetIndex: number | undefined, originalEvent: DragEvent, raw = true): boolean | IListDragOverReaction { + return this.dnd.onDragOver(asAsyncDataTreeDragAndDropData(data), targetNode && targetNode.element as T, targetIndex, originalEvent); + } + + drop(data: IDragAndDropData, targetNode: IAsyncDataTreeNode | undefined, targetIndex: number | undefined, originalEvent: DragEvent): void { + this.dnd.drop(asAsyncDataTreeDragAndDropData(data), targetNode && targetNode.element as T, targetIndex, originalEvent); + } +} + function asObjectTreeOptions(options?: IAsyncDataTreeOptions): IObjectTreeOptions, TFilterData> | undefined { return options && { ...options, + collapseByDefault: true, identityProvider: options.identityProvider && { getId(el) { return options.identityProvider!.getId(el.element as T); } }, + dnd: options.dnd && new AsyncDataTreeNodeListDragAndDrop(options.dnd), multipleSelectionController: options.multipleSelectionController && { isSelectionSingleChangeEvent(e) { return options.multipleSelectionController!.isSelectionSingleChangeEvent({ ...e, element: e.element } as any); @@ -149,28 +227,65 @@ function asObjectTreeOptions(options?: IAsyncDataTreeOpt } }, keyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && { + ...options.keyboardNavigationLabelProvider, getKeyboardNavigationLabel(e) { return options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(e.element as T); } }, - sorter: options.sorter && { - compare(a, b) { - return options.sorter!.compare(a.element as T, b.element as T); - } - } + sorter: undefined, + expandOnlyOnTwistieClick: typeof options.expandOnlyOnTwistieClick === 'undefined' ? undefined : ( + typeof options.expandOnlyOnTwistieClick !== 'function' ? options.expandOnlyOnTwistieClick : ( + e => (options.expandOnlyOnTwistieClick as ((e: T) => boolean))(e.element as T) + ) + ), + ariaProvider: undefined }; } -function asTreeElement(node: IAsyncDataTreeNode): ITreeElement> { +function asTreeElement(node: IAsyncDataTreeNode, viewStateContext?: IAsyncDataTreeViewStateContext): ITreeElement> { + let collapsed: boolean | undefined; + + if (viewStateContext && viewStateContext.viewState.expanded && node.id && viewStateContext.viewState.expanded.indexOf(node.id) > -1) { + collapsed = false; + } else { + collapsed = node.collapsedByDefault; + } + + node.collapsedByDefault = undefined; + return { element: node, - children: Iterator.map(Iterator.fromArray(node.children!), asTreeElement) + children: node.hasChildren ? Iterator.map(Iterator.fromArray(node.children), child => asTreeElement(child, viewStateContext)) : [], + collapsible: node.hasChildren, + collapsed }; } -export interface IAsyncDataTreeOptions extends IAbstractTreeOptions { - identityProvider?: IIdentityProvider; - sorter?: ITreeSorter; +export interface IAsyncDataTreeOptionsUpdate extends IAbstractTreeOptionsUpdate { } + +export interface IAsyncDataTreeOptions extends IAsyncDataTreeOptionsUpdate, Pick, Exclude, 'collapseByDefault'>> { + readonly collapseByDefault?: { (e: T): boolean; }; + readonly identityProvider?: IIdentityProvider; + readonly sorter?: ITreeSorter; + readonly autoExpandSingleChildren?: boolean; +} + +export interface IAsyncDataTreeViewState { + readonly focus?: string[]; + readonly selection?: string[]; + readonly expanded?: string[]; + readonly scrollTop?: number; +} + +interface IAsyncDataTreeViewStateContext { + readonly viewState: IAsyncDataTreeViewState; + readonly selection: IAsyncDataTreeNode[]; + readonly focus: IAsyncDataTreeNode[]; +} + +function dfs(node: IAsyncDataTreeNode, fn: (node: IAsyncDataTreeNode) => void): void { + fn(node); + node.children.forEach(child => dfs(child, fn)); } export class AsyncDataTree implements IDisposable { @@ -178,55 +293,78 @@ export class AsyncDataTree implements IDisposable private readonly tree: ObjectTree, TFilterData>; private readonly root: IAsyncDataTreeNode; private readonly nodes = new Map>(); - private readonly refreshPromises = new Map, Promise>(); - private readonly identityProvider?: IIdentityProvider; + private readonly sorter?: ITreeSorter; + private readonly collapseByDefault?: { (e: T): boolean; }; - private readonly _onDidChangeNodeState = new Emitter>(); + private readonly subTreeRefreshPromises = new Map, Promise>(); + private readonly refreshPromises = new Map, CancelablePromise>(); + + private readonly identityProvider?: IIdentityProvider; + private readonly autoExpandSingleChildren: boolean; + + private readonly _onDidRender = new Emitter(); + private readonly _onDidChangeNodeSlowState = new Emitter>(); protected readonly disposables: IDisposable[] = []; + get onDidScroll(): Event { return this.tree.onDidScroll; } + get onDidChangeFocus(): Event> { return Event.map(this.tree.onDidChangeFocus, asTreeEvent); } get onDidChangeSelection(): Event> { return Event.map(this.tree.onDidChangeSelection, asTreeEvent); } get onDidOpen(): Event> { return Event.map(this.tree.onDidOpen, asTreeEvent); } - private readonly _onDidResolveChildren = new Emitter>(); - readonly onDidResolveChildren: Event> = this._onDidResolveChildren.event; - + get onKeyDown(): Event { return this.tree.onKeyDown; } get onMouseClick(): Event> { return Event.map(this.tree.onMouseClick, asTreeMouseEvent); } get onMouseDblClick(): Event> { return Event.map(this.tree.onMouseDblClick, asTreeMouseEvent); } get onContextMenu(): Event> { return Event.map(this.tree.onContextMenu, asTreeContextMenuEvent); } get onDidFocus(): Event { return this.tree.onDidFocus; } get onDidBlur(): Event { return this.tree.onDidBlur; } + get onDidChangeCollapseState(): Event | null, TFilterData>> { return this.tree.onDidChangeCollapseState; } + + get onDidUpdateOptions(): Event { return this.tree.onDidUpdateOptions; } + + get filterOnType(): boolean { return this.tree.filterOnType; } + get openOnSingleClick(): boolean { return this.tree.openOnSingleClick; } + get expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) { + if (typeof this.tree.expandOnlyOnTwistieClick === 'boolean') { + return this.tree.expandOnlyOnTwistieClick; + } + + const fn = this.tree.expandOnlyOnTwistieClick; + return element => fn(this.nodes.get((element === this.root.element ? null : element) as T) || null); + } + get onDidDispose(): Event { return this.tree.onDidDispose; } constructor( container: HTMLElement, delegate: IListVirtualDelegate, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], private dataSource: IAsyncDataSource, - options?: IAsyncDataTreeOptions + options: IAsyncDataTreeOptions = {} ) { - this.identityProvider = options && options.identityProvider; + this.identityProvider = options.identityProvider; + this.autoExpandSingleChildren = typeof options.autoExpandSingleChildren === 'undefined' ? false : options.autoExpandSingleChildren; + this.sorter = options.sorter; + this.collapseByDefault = options.collapseByDefault; const objectTreeDelegate = new ComposedTreeDelegate>(delegate); - const objectTreeRenderers = renderers.map(r => new DataTreeRenderer(r, this._onDidChangeNodeState.event)); + const objectTreeRenderers = renderers.map(r => new DataTreeRenderer(r, this._onDidChangeNodeSlowState.event)); const objectTreeOptions = asObjectTreeOptions(options) || {}; - objectTreeOptions.collapseByDefault = true; this.tree = new ObjectTree(container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions); - this.root = { + this.root = createAsyncDataTreeNode({ element: undefined!, parent: null, - state: AsyncDataTreeNodeState.Uninitialized, - }; + hasChildren: true + }); if (this.identityProvider) { this.root = { ...this.root, - id: null, - children: [], + id: null }; } @@ -235,6 +373,10 @@ export class AsyncDataTree implements IDisposable this.tree.onDidChangeCollapseState(this._onDidChangeCollapseState, this, this.disposables); } + updateOptions(options: IAsyncDataTreeOptionsUpdate = {}): void { + this.tree.updateOptions(options); + } + // Widget getHTMLElement(): HTMLElement { @@ -265,63 +407,127 @@ export class AsyncDataTree implements IDisposable return this.tree.renderHeight; } + get firstVisibleElement(): T { + return this.tree.firstVisibleElement!.element as T; + } + + get lastVisibleElement(): T { + return this.tree.lastVisibleElement!.element as T; + } + domFocus(): void { this.tree.domFocus(); } - layout(height?: number): void { - this.tree.layout(height); + layout(height?: number, width?: number): void { + this.tree.layout(height, width); } style(styles: IListStyles): void { this.tree.style(styles); } - // Data Tree + // Model getInput(): TInput | undefined { return this.root.element as TInput; } - setInput(input: TInput): Promise { + async setInput(input: TInput, viewState?: IAsyncDataTreeViewState): Promise { + this.refreshPromises.forEach(promise => promise.cancel()); + this.refreshPromises.clear(); + this.root.element = input!; - return this.refresh(input); + + const viewStateContext = viewState && { viewState, focus: [], selection: [] } as IAsyncDataTreeViewStateContext; + + await this.updateChildren(input, true, viewStateContext); + + if (viewStateContext) { + this.tree.setFocus(viewStateContext.focus); + this.tree.setSelection(viewStateContext.selection); + } + + if (viewState && typeof viewState.scrollTop === 'number') { + this.scrollTop = viewState.scrollTop; + } } - refresh(element: TInput | T = this.root.element, recursive = true): Promise { + async updateChildren(element: TInput | T = this.root.element, recursive = true, viewStateContext?: IAsyncDataTreeViewStateContext): Promise { if (typeof this.root.element === 'undefined') { throw new Error('Tree input not set'); } - return this.refreshNode(this.getDataNode(element), recursive, ChildrenResolutionReason.Refresh); + if (this.root.loading) { + await this.subTreeRefreshPromises.get(this.root)!; + await Event.toPromise(this._onDidRender.event); + } + + await this.refreshAndRenderNode(this.getDataNode(element), recursive, ChildrenResolutionReason.Refresh, viewStateContext); + } + + resort(element: TInput | T = this.root.element, recursive = true): void { + this.tree.resort(this.getDataNode(element), recursive); + } + + hasNode(element: TInput | T): boolean { + return element === this.root.element || this.nodes.has(element as T); + } + + // View + + rerender(element?: T): void { + if (element === undefined || element === this.root.element) { + this.tree.rerender(); + return; + } + + const node = this.getDataNode(element); + this.tree.rerender(node); + } + + updateWidth(element: T): void { + const node = this.getDataNode(element); + this.tree.updateWidth(node); } // Tree - getNode(element: TInput | T): ITreeNode { + getNode(element: TInput | T = this.root.element): ITreeNode { const dataNode = this.getDataNode(element); const node = this.tree.getNode(dataNode === this.root ? null : dataNode); return new AsyncDataTreeNodeWrapper(node); } collapse(element: T, recursive: boolean = false): boolean { - return this.tree.collapse(this.getDataNode(element), recursive); + const node = this.getDataNode(element); + return this.tree.collapse(node === this.root ? null : node, recursive); } async expand(element: T, recursive: boolean = false): Promise { + if (typeof this.root.element === 'undefined') { + throw new Error('Tree input not set'); + } + + if (this.root.loading) { + await this.subTreeRefreshPromises.get(this.root)!; + await Event.toPromise(this._onDidRender.event); + } + const node = this.getDataNode(element); - if (!this.tree.isCollapsed(node)) { + if (node !== this.root && !node.loading && !this.tree.isCollapsed(node)) { return false; } - this.tree.expand(node, recursive); + const result = this.tree.expand(node === this.root ? null : node, recursive); - if (node.state !== AsyncDataTreeNodeState.Loaded) { - await this.refreshNode(node, false, ChildrenResolutionReason.Expand); + if (node.loading) { + await this.subTreeRefreshPromises.get(node)!; + await Event.toPromise(this._onDidRender.event); } - return true; + return result; } toggleCollapsed(element: T, recursive: boolean = false): boolean { @@ -344,6 +550,10 @@ export class AsyncDataTree implements IDisposable return this.tree.isCollapsed(this.getDataNode(element)); } + toggleKeyboardNavigation(): void { + this.tree.toggleKeyboardNavigation(); + } + refilter(): void { this.tree.refilter(); } @@ -392,9 +602,9 @@ export class AsyncDataTree implements IDisposable return nodes.map(n => n!.element as T); } - open(elements: T[]): void { + open(elements: T[], browserEvent?: UIEvent): void { const nodes = elements.map(e => this.getDataNode(e)); - this.tree.open(nodes); + this.tree.open(nodes, browserEvent); } reveal(element: T, relativeTop?: number): void { @@ -418,197 +628,266 @@ export class AsyncDataTree implements IDisposable return (node && node.element)!; } - getLastElementAncestor(element: TInput | T = this.root.element): TInput | T | undefined { - const dataNode = this.getDataNode(element); - const node = this.tree.getLastElementAncestor(dataNode === this.root ? null : dataNode); - return (node && node.element)!; - } - - // List - - get visibleNodeCount(): number { - return this.tree.visibleNodeCount; - } - // Implementation private getDataNode(element: TInput | T): IAsyncDataTreeNode { - const node: IAsyncDataTreeNode = this.nodes.get((element === this.root.element ? null : element) as T); + const node: IAsyncDataTreeNode | undefined = this.nodes.get((element === this.root.element ? null : element) as T); - if (typeof node === 'undefined') { + if (!node) { throw new Error(`Data tree node not found: ${element}`); } return node; } - private async refreshNode(node: IAsyncDataTreeNode, recursive: boolean, reason: ChildrenResolutionReason): Promise { - await this._refreshNode(node, recursive, reason); + private async refreshAndRenderNode(node: IAsyncDataTreeNode, recursive: boolean, reason: ChildrenResolutionReason, viewStateContext?: IAsyncDataTreeViewStateContext): Promise { + await this.refreshNode(node, recursive, viewStateContext); + this.render(node, viewStateContext); - if (recursive && node.children) { - await Promise.all(node.children.map(child => this.refreshNode(child, recursive, reason))); + if (node !== this.root && this.autoExpandSingleChildren && reason === ChildrenResolutionReason.Expand) { + const treeNode = this.tree.getNode(node); + const visibleChildren = treeNode.children.filter(node => node.visible); + + if (visibleChildren.length === 1) { + await this.tree.expand(visibleChildren[0].element, false); + } } } - private _refreshNode(node: IAsyncDataTreeNode, recursive: boolean, reason: ChildrenResolutionReason): Promise { + private async refreshNode(node: IAsyncDataTreeNode, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): Promise { + let result: Promise | undefined; + + this.subTreeRefreshPromises.forEach((refreshPromise, refreshNode) => { + if (!result && intersects(refreshNode, node)) { + result = refreshPromise.then(() => this.refreshNode(node, recursive, viewStateContext)); + } + }); + + if (result) { + return result; + } + + result = this.doRefreshSubTree(node, recursive, viewStateContext); + this.subTreeRefreshPromises.set(node, result); + + try { + await result; + } finally { + this.subTreeRefreshPromises.delete(node); + } + } + + private async doRefreshSubTree(node: IAsyncDataTreeNode, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): Promise { + node.loading = true; + + try { + const childrenToRefresh = await this.doRefreshNode(node, recursive, viewStateContext); + node.stale = false; + + await Promise.all(childrenToRefresh.map(child => this.doRefreshSubTree(child, recursive, viewStateContext))); + } finally { + node.loading = false; + } + } + + private async doRefreshNode(node: IAsyncDataTreeNode, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): Promise[]> { + node.hasChildren = !!this.dataSource.hasChildren(node.element!); + + let childrenPromise: Promise; + + if (!node.hasChildren) { + childrenPromise = Promise.resolve([]); + } else { + const slowTimeout = timeout(800); + + slowTimeout.then(() => { + node.slow = true; + this._onDidChangeNodeSlowState.fire(node); + }, _ => null); + + childrenPromise = this.doGetChildren(node) + .finally(() => slowTimeout.cancel()); + } + + try { + const children = await childrenPromise; + return this.setChildren(node, children, recursive, viewStateContext); + } catch (err) { + if (node !== this.root) { + this.tree.collapse(node === this.root ? null : node); + } + + if (isPromiseCanceledError(err)) { + return []; + } + + throw err; + } finally { + if (node.slow) { + node.slow = false; + this._onDidChangeNodeSlowState.fire(node); + } + } + } + + private doGetChildren(node: IAsyncDataTreeNode): Promise { let result = this.refreshPromises.get(node); if (result) { return result; } - result = this.doRefresh(node, recursive, reason); + result = createCancelablePromise(async () => { + const children = await this.dataSource.getChildren(node.element!); + + if (this.sorter) { + children.sort(this.sorter.compare.bind(this.sorter)); + } + + return children; + }); + this.refreshPromises.set(node, result); - return always(result, () => this.refreshPromises.delete(node)); - } - private doRefresh(node: IAsyncDataTreeNode, recursive: boolean, reason: ChildrenResolutionReason): Promise { - const hasChildren = !!this.dataSource.hasChildren(node.element!); - - if (!hasChildren) { - this.setChildren(node, [], recursive); - return Promise.resolve(); - } else if (node !== this.root && (!this.tree.isCollapsible(node) || this.tree.isCollapsed(node))) { - return Promise.resolve(); - } else { - node.state = AsyncDataTreeNodeState.Loading; - this._onDidChangeNodeState.fire(node); - - const slowTimeout = timeout(800); - - slowTimeout.then(() => { - node.state = AsyncDataTreeNodeState.Slow; - this._onDidChangeNodeState.fire(node); - }, _ => null); - - return Promise.resolve(this.dataSource.getChildren(node.element!)) - .then(children => { - slowTimeout.cancel(); - node.state = AsyncDataTreeNodeState.Loaded; - this._onDidChangeNodeState.fire(node); - - this.setChildren(node, children, recursive); - this._onDidResolveChildren.fire({ element: node.element as T, reason }); - }, err => { - slowTimeout.cancel(); - node.state = AsyncDataTreeNodeState.Uninitialized; - this._onDidChangeNodeState.fire(node); - - if (node !== this.root) { - this.tree.collapse(node); - } - - return Promise.reject(err); - }); - } + return result.finally(() => this.refreshPromises.delete(node)); } private _onDidChangeCollapseState({ node, deep }: ICollapseStateChangeEvent, any>): void { - if (!node.collapsed && node.element.state === AsyncDataTreeNodeState.Uninitialized) { + if (!node.collapsed && node.element.stale) { if (deep) { this.collapse(node.element.element as T); } else { - this.refreshNode(node.element, false, ChildrenResolutionReason.Expand); + this.refreshAndRenderNode(node.element, false, ChildrenResolutionReason.Expand) + .catch(onUnexpectedError); } } } - private setChildren(node: IAsyncDataTreeNode, childrenElements: T[], recursive: boolean): void { - let nodeChildren: Map> | undefined; + private setChildren(node: IAsyncDataTreeNode, childrenElements: T[], recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): IAsyncDataTreeNode[] { + // perf: if the node was and still is a leaf, avoid all this hassle + if (node.children.length === 0 && childrenElements.length === 0) { + return []; + } - if (this.identityProvider) { - nodeChildren = new Map(); + const nodesToForget = new Map>(); + const childrenTreeNodesById = new Map | null, TFilterData>>(); - for (const child of node.children!) { - nodeChildren.set(child.id!, child); + for (const child of node.children) { + nodesToForget.set(child.element as T, child); + + if (this.identityProvider) { + childrenTreeNodesById.set(child.id!, this.tree.getNode(child)); } } - const children = childrenElements.map>>(element => { + const childrenToRefresh: IAsyncDataTreeNode[] = []; + + const children = childrenElements.map>(element => { + const hasChildren = !!this.dataSource.hasChildren(element); + if (!this.identityProvider) { - return { - element: { - element, - parent: node, - state: AsyncDataTreeNodeState.Uninitialized - }, - collapsible: !!this.dataSource.hasChildren(element), - collapsed: true - }; + const asyncDataTreeNode = createAsyncDataTreeNode({ element, parent: node, hasChildren }); + + if (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) { + asyncDataTreeNode.collapsedByDefault = false; + childrenToRefresh.push(asyncDataTreeNode); + } + + return asyncDataTreeNode; } const id = this.identityProvider.getId(element).toString(); - const asyncDataTreeNode = nodeChildren!.get(id); + const childNode = childrenTreeNodesById.get(id); - if (!asyncDataTreeNode) { - return { - element: { - element, - parent: node, - id, - children: [], - state: AsyncDataTreeNodeState.Uninitialized - }, - collapsible: !!this.dataSource.hasChildren(element), - collapsed: true - }; - } + if (childNode) { + const asyncDataTreeNode = childNode.element!; - asyncDataTreeNode.element = element; + nodesToForget.delete(asyncDataTreeNode.element as T); + this.nodes.delete(asyncDataTreeNode.element as T); + this.nodes.set(element, asyncDataTreeNode); - const collapsible = !!this.dataSource.hasChildren(element); - const collapsed = !collapsible || this.tree.isCollapsed(asyncDataTreeNode); + asyncDataTreeNode.element = element; + asyncDataTreeNode.hasChildren = hasChildren; - if (recursive) { - asyncDataTreeNode.state = AsyncDataTreeNodeState.Uninitialized; - - if (this.tree.isCollapsed(asyncDataTreeNode)) { - asyncDataTreeNode.children!.length = 0; - - return { - element: asyncDataTreeNode, - collapsible, - collapsed - }; + if (recursive) { + if (childNode.collapsed) { + dfs(asyncDataTreeNode, node => node.stale = true); + } else { + childrenToRefresh.push(asyncDataTreeNode); + } + } else if (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) { + asyncDataTreeNode.collapsedByDefault = false; + childrenToRefresh.push(asyncDataTreeNode); } + + return asyncDataTreeNode; } - let children: Iterator>> | undefined = undefined; + const childAsyncDataTreeNode = createAsyncDataTreeNode({ element, parent: node, id, hasChildren }); - if (collapsible) { - children = Iterator.map(Iterator.fromArray(asyncDataTreeNode.children!), asTreeElement); + if (viewStateContext && viewStateContext.viewState.focus && viewStateContext.viewState.focus.indexOf(id) > -1) { + viewStateContext.focus.push(childAsyncDataTreeNode); } - return { - element: asyncDataTreeNode, - children, - collapsible, - collapsed - }; + if (viewStateContext && viewStateContext.viewState.selection && viewStateContext.viewState.selection.indexOf(id) > -1) { + viewStateContext.selection.push(childAsyncDataTreeNode); + } + + if (viewStateContext && viewStateContext.viewState.expanded && viewStateContext.viewState.expanded.indexOf(id) > -1) { + childrenToRefresh.push(childAsyncDataTreeNode); + } else if (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) { + childAsyncDataTreeNode.collapsedByDefault = false; + childrenToRefresh.push(childAsyncDataTreeNode); + } + + return childAsyncDataTreeNode; }); - const insertedElements = new Set(); - - const onDidCreateNode = (treeNode: ITreeNode, TFilterData>) => { - if (treeNode.element.element) { - insertedElements.add(treeNode.element.element as T); - this.nodes.set(treeNode.element.element as T, treeNode.element); - } - }; - - const onDidDeleteNode = (treeNode: ITreeNode, TFilterData>) => { - if (treeNode.element.element) { - if (!insertedElements.has(treeNode.element.element as T)) { - this.nodes.delete(treeNode.element.element as T); - } - } - }; - - this.tree.setChildren(node === this.root ? null : node, children, onDidCreateNode, onDidDeleteNode); - - if (this.identityProvider) { - node.children!.splice(0, node.children!.length, ...children.map(c => c.element)); + for (const node of values(nodesToForget)) { + dfs(node, node => this.nodes.delete(node.element as T)); } + + for (const child of children) { + this.nodes.set(child.element as T, child); + } + + node.children.splice(0, node.children.length, ...children); + + return childrenToRefresh; + } + + private render(node: IAsyncDataTreeNode, viewStateContext?: IAsyncDataTreeViewStateContext): void { + const children = node.children.map(c => asTreeElement(c, viewStateContext)); + this.tree.setChildren(node === this.root ? null : node, children); + this._onDidRender.fire(); + } + + // view state + + getViewState(): IAsyncDataTreeViewState { + if (!this.identityProvider) { + throw new Error('Can\'t get tree view state without an identity provider'); + } + + const getId = (element: T) => this.identityProvider!.getId(element).toString(); + const focus = this.getFocus().map(getId); + const selection = this.getSelection().map(getId); + + const expanded: string[] = []; + const root = this.tree.getNode(); + const queue = [root]; + + while (queue.length > 0) { + const node = queue.shift()!; + + if (node !== root && node.collapsible && !node.collapsed) { + expanded.push(getId(node.element!.element as T)); + } + + queue.push(...node.children); + } + + return { focus, selection, expanded, scrollTop: this.scrollTop }; } dispose(): void { diff --git a/src/vs/base/browser/ui/tree/compressedObjectTree.ts b/src/vs/base/browser/ui/tree/compressedObjectTree.ts new file mode 100644 index 00000000000..dd98e865909 --- /dev/null +++ b/src/vs/base/browser/ui/tree/compressedObjectTree.ts @@ -0,0 +1,56 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Iterator, ISequence } from 'vs/base/common/iterator'; +import { AbstractTree, IAbstractTreeOptions } from 'vs/base/browser/ui/tree/abstractTree'; +import { ISpliceable } from 'vs/base/common/sequence'; +import { ITreeNode, ITreeModel, ITreeElement, ITreeRenderer, ITreeSorter, ICollapseStateChangeEvent } from 'vs/base/browser/ui/tree/tree'; +import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { Event } from 'vs/base/common/event'; +import { CompressedTreeModel, ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; + +export interface IObjectTreeOptions extends IAbstractTreeOptions { + sorter?: ITreeSorter; +} + +export class CompressedObjectTree, TFilterData = void> extends AbstractTree | null, TFilterData, T | null> { + + protected model!: CompressedTreeModel; + + get onDidChangeCollapseState(): Event | null, TFilterData>> { return this.model.onDidChangeCollapseState; } + + constructor( + container: HTMLElement, + delegate: IListVirtualDelegate>, + renderers: ITreeRenderer, TFilterData, any>[], + options: IObjectTreeOptions, TFilterData> = {} + ) { + super(container, delegate, renderers, options); + } + + setChildren( + element: T | null, + children?: ISequence> + ): Iterator> { + return this.model.setChildren(element, children); + } + + rerender(element?: T): void { + if (element === undefined) { + this.view.rerender(); + return; + } + + this.model.rerender(element); + } + + resort(element: T, recursive = true): void { + this.model.resort(element, recursive); + } + + protected createModel(view: ISpliceable, TFilterData>>, options: IObjectTreeOptions, TFilterData>): ITreeModel | null, TFilterData, T | null> { + return new CompressedTreeModel(view, options); + } +} diff --git a/src/vs/base/browser/ui/tree/compressedObjectTreeModel.ts b/src/vs/base/browser/ui/tree/compressedObjectTreeModel.ts new file mode 100644 index 00000000000..339dfdbbe9e --- /dev/null +++ b/src/vs/base/browser/ui/tree/compressedObjectTreeModel.ts @@ -0,0 +1,418 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ISpliceable } from 'vs/base/common/sequence'; +import { Iterator, ISequence } from 'vs/base/common/iterator'; +import { Event } from 'vs/base/common/event'; +import { ITreeModel, ITreeNode, ITreeElement, ICollapseStateChangeEvent, ITreeModelSpliceEvent } from 'vs/base/browser/ui/tree/tree'; +import { IObjectTreeModelOptions, ObjectTreeModel, IObjectTreeModel } from 'vs/base/browser/ui/tree/objectTreeModel'; + +export interface ICompressedTreeElement extends ITreeElement { + readonly children?: Iterator> | ICompressedTreeElement[]; + readonly incompressible?: boolean; +} + +export interface ICompressedTreeNode { + readonly elements: T[]; + readonly incompressible: boolean; +} + +export function compress(element: ICompressedTreeElement): ITreeElement> { + const elements = [element.element]; + const incompressible = element.incompressible || false; + + let childrenIterator: Iterator>; + let children: ITreeElement[]; + + while (true) { + childrenIterator = Iterator.from(element.children); + children = Iterator.collect(childrenIterator, 2); + + if (children.length !== 1) { + break; + } + + element = children[0]; + + if (element.incompressible) { + break; + } + + elements.push(element.element); + } + + return { + element: { elements, incompressible }, + children: Iterator.map(Iterator.concat(Iterator.fromArray(children), childrenIterator), compress) + }; +} + +export function _decompress(element: ITreeElement>, index = 0): ICompressedTreeElement { + let children: Iterator>; + + if (index < element.element.elements.length - 1) { + children = Iterator.single(_decompress(element, index + 1)); + } else { + children = Iterator.map(Iterator.from(element.children), el => _decompress(el, 0)); + } + + if (index === 0 && element.element.incompressible) { + return { element: element.element.elements[index], children, incompressible: true }; + } + + return { element: element.element.elements[index], children }; +} + +export function decompress(element: ITreeElement>): ICompressedTreeElement { + return _decompress(element, 0); +} + +export function splice(treeElement: ICompressedTreeElement, element: T, children: Iterator>): ICompressedTreeElement { + if (treeElement.element === element) { + return { element, children }; + } + + return { + ...treeElement, + children: Iterator.map(Iterator.from(treeElement.children), e => splice(e, element, children)) + }; +} + +export interface ICompressedTreeModelOptions extends IObjectTreeModelOptions, TFilterData> { } + +export class CompressedTreeModel, TFilterData extends NonNullable = void> implements ITreeModel | null, TFilterData, T | null> { + + readonly rootRef = null; + + get onDidSplice(): Event | null, TFilterData>> { return this.model.onDidSplice; } + get onDidChangeCollapseState(): Event, TFilterData>> { return this.model.onDidChangeCollapseState; } + get onDidChangeRenderNodeCount(): Event, TFilterData>> { return this.model.onDidChangeRenderNodeCount; } + + private model: ObjectTreeModel, TFilterData>; + private nodes = new Map>(); + + get size(): number { return this.nodes.size; } + + constructor(list: ISpliceable, TFilterData>>, options: ICompressedTreeModelOptions = {}) { + this.model = new ObjectTreeModel(list, options); + } + + setChildren( + element: T | null, + children: ISequence> | undefined, + onDidCreateNode?: (node: ITreeNode, TFilterData>) => void, + onDidDeleteNode?: (node: ITreeNode, TFilterData>) => void + ): Iterator> { + const insertedElements = new Set(); + const _onDidCreateNode = (node: ITreeNode, TFilterData>) => { + for (const element of node.element.elements) { + insertedElements.add(element); + this.nodes.set(element, node.element); + } + + // if (this.identityProvider) { + // const id = this.identityProvider.getId(node.element).toString(); + // insertedElementIds.add(id); + // this.nodesByIdentity.set(id, node); + // } + + if (onDidCreateNode) { + onDidCreateNode(node); + } + }; + + const _onDidDeleteNode = (node: ITreeNode, TFilterData>) => { + for (const element of node.element.elements) { + if (!insertedElements.has(element)) { + this.nodes.delete(element); + } + } + + // if (this.identityProvider) { + // const id = this.identityProvider.getId(node.element).toString(); + // if (!insertedElementIds.has(id)) { + // this.nodesByIdentity.delete(id); + // } + // } + + if (onDidDeleteNode) { + onDidDeleteNode(node); + } + }; + + if (element === null) { + const compressedChildren = Iterator.map(Iterator.from(children), compress); + const result = this.model.setChildren(null, compressedChildren, _onDidCreateNode, _onDidDeleteNode); + return Iterator.map(result, decompress); + } + + const compressedNode = this.nodes.get(element); + const node = this.model.getNode(compressedNode) as ITreeNode, TFilterData>; + const parent = node.parent!; + + const decompressedElement = decompress(node); + const splicedElement = splice(decompressedElement, element, Iterator.from(children)); + const recompressedElement = compress(splicedElement); + + const parentChildren = parent.children + .map(child => child === node ? recompressedElement : child); + + this.model.setChildren(parent.element, parentChildren, _onDidCreateNode, _onDidDeleteNode); + + // TODO + return Iterator.empty(); + } + + getListIndex(location: T | null): number { + const node = this.getCompressedNode(location); + return this.model.getListIndex(node); + } + + getListRenderCount(location: T | null): number { + const node = this.getCompressedNode(location); + return this.model.getListRenderCount(node); + } + + getNode(location?: T | null | undefined): ITreeNode | null, TFilterData> { + if (typeof location === 'undefined') { + return this.model.getNode(); + } + + const node = this.getCompressedNode(location); + return this.model.getNode(node); + } + + // TODO: review this + getNodeLocation(node: ITreeNode, TFilterData>): T | null { + const compressedNode = this.model.getNodeLocation(node); + + if (compressedNode === null) { + return null; + } + + return compressedNode.elements[compressedNode.elements.length - 1]; + } + + // TODO: review this + getParentNodeLocation(location: T | null): T | null { + const compressedNode = this.getCompressedNode(location); + const parentNode = this.model.getParentNodeLocation(compressedNode); + + if (parentNode === null) { + return null; + } + + return parentNode.elements[parentNode.elements.length - 1]; + } + + getParentElement(location: T | null): ICompressedTreeNode | null { + const compressedNode = this.getCompressedNode(location); + return this.model.getParentElement(compressedNode); + } + + getFirstElementChild(location: T | null): ICompressedTreeNode | null | undefined { + const compressedNode = this.getCompressedNode(location); + return this.model.getFirstElementChild(compressedNode); + } + + getLastElementAncestor(location?: T | null | undefined): ICompressedTreeNode | null | undefined { + const compressedNode = typeof location === 'undefined' ? undefined : this.getCompressedNode(location); + return this.model.getLastElementAncestor(compressedNode); + } + + isCollapsible(location: T | null): boolean { + const compressedNode = this.getCompressedNode(location); + return this.model.isCollapsible(compressedNode); + } + + isCollapsed(location: T | null): boolean { + const compressedNode = this.getCompressedNode(location); + return this.model.isCollapsed(compressedNode); + } + + setCollapsed(location: T | null, collapsed?: boolean | undefined, recursive?: boolean | undefined): boolean { + const compressedNode = this.getCompressedNode(location); + return this.model.setCollapsed(compressedNode, collapsed, recursive); + } + + expandTo(location: T | null): void { + const compressedNode = this.getCompressedNode(location); + this.model.expandTo(compressedNode); + } + + rerender(location: T | null): void { + const compressedNode = this.getCompressedNode(location); + this.model.rerender(compressedNode); + } + + refilter(): void { + this.model.refilter(); + } + + resort(location: T | null = null, recursive = true): void { + const compressedNode = this.getCompressedNode(location); + this.model.resort(compressedNode, recursive); + } + + private getCompressedNode(element: T | null): ICompressedTreeNode | null { + if (element === null) { + return null; + } + + const node = this.nodes.get(element); + + if (!node) { + throw new Error(`Tree element not found: ${element}`); + } + + return node; + } +} + +export type ElementMapper = (elements: T[]) => T; +export const DefaultElementMapper: ElementMapper = elements => elements[elements.length - 1]; + +export type NodeMapper = (node: ITreeNode | null, TFilterData>) => ITreeNode; + +function mapNode(elementMapper: ElementMapper, node: ITreeNode | null, TFilterData>): ITreeNode { + return { + ...node, + element: node.element === null ? null : elementMapper(node.element.elements), + children: node.children.map(child => mapNode(elementMapper, child)), + parent: typeof node.parent === 'undefined' ? node.parent : mapNode(elementMapper, node.parent) + }; +} + +function createNodeMapper(elementMapper: ElementMapper): NodeMapper { + return node => mapNode(elementMapper, node); +} + +export interface ICompressedObjectTreeModelOptions extends ICompressedTreeModelOptions { + readonly elementMapper?: ElementMapper; +} + +export class CompressedObjectTreeModel, TFilterData extends NonNullable = void> implements IObjectTreeModel { + + readonly rootRef = null; + + get onDidSplice(): Event> { + return Event.map(this.model.onDidSplice, ({ insertedNodes, deletedNodes }) => ({ + insertedNodes: insertedNodes.map(this.mapNode), + deletedNodes: deletedNodes.map(this.mapNode), + })); + } + + get onDidChangeCollapseState(): Event> { + return Event.map(this.model.onDidChangeCollapseState, ({ node, deep }) => ({ + node: this.mapNode(node), + deep + })); + } + + get onDidChangeRenderNodeCount(): Event> { + return Event.map(this.model.onDidChangeRenderNodeCount, this.mapNode); + } + + private mapElement: ElementMapper; + private mapNode: NodeMapper; + private model: CompressedTreeModel; + + constructor( + list: ISpliceable, TFilterData>>, + options: ICompressedObjectTreeModelOptions = {} + ) { + this.mapElement = options.elementMapper || DefaultElementMapper; + this.mapNode = createNodeMapper(this.mapElement); + this.model = new CompressedTreeModel(list, options); + } + + setChildren( + element: T | null, + children: ISequence> | undefined + ): Iterator> { + this.model.setChildren(element, children); + + // TODO + return Iterator.empty(); + } + + getListIndex(location: T | null): number { + return this.model.getListIndex(location); + } + + getListRenderCount(location: T | null): number { + return this.model.getListRenderCount(location); + } + + getNode(location?: T | null | undefined): ITreeNode { + return this.mapNode(this.model.getNode(location)); + } + + getNodeLocation(node: ITreeNode): T | null { + return node.element; + } + + getParentNodeLocation(location: T | null): T | null { + return this.model.getParentNodeLocation(location); + } + + getParentElement(location: T | null): T | null { + const result = this.model.getParentElement(location); + + if (result === null) { + return result; + } + + return this.mapElement(result.elements); + } + + getFirstElementChild(location: T | null): T | null | undefined { + const result = this.model.getFirstElementChild(location); + + if (result === null || typeof result === 'undefined') { + return result; + } + + return this.mapElement(result.elements); + } + + getLastElementAncestor(location?: T | null | undefined): T | null | undefined { + const result = this.model.getLastElementAncestor(location); + + if (result === null || typeof result === 'undefined') { + return result; + } + + return this.mapElement(result.elements); + } + + isCollapsible(location: T | null): boolean { + return this.model.isCollapsible(location); + } + + isCollapsed(location: T | null): boolean { + return this.model.isCollapsed(location); + } + + setCollapsed(location: T | null, collapsed?: boolean | undefined, recursive?: boolean | undefined): boolean { + return this.model.setCollapsed(location, collapsed, recursive); + } + + expandTo(location: T | null): void { + return this.model.expandTo(location); + } + + rerender(location: T | null): void { + return this.model.rerender(location); + } + + refilter(): void { + return this.model.refilter(); + } + + resort(element: T | null = null, recursive = true): void { + return this.model.resort(element, recursive); + } +} \ No newline at end of file diff --git a/src/vs/base/browser/ui/tree/dataTree.ts b/src/vs/base/browser/ui/tree/dataTree.ts index f6a4006af84..9a67a381edb 100644 --- a/src/vs/base/browser/ui/tree/dataTree.ts +++ b/src/vs/base/browser/ui/tree/dataTree.ts @@ -17,20 +17,22 @@ export interface IDataTreeOptions extends IAbstractTreeOp export interface IDataTreeViewState { readonly focus: string[]; readonly selection: string[]; - readonly collapsed: string[]; + readonly expanded: string[]; + readonly scrollTop: number; } export class DataTree extends AbstractTree { - protected model: ObjectTreeModel; + protected model!: ObjectTreeModel; private input: TInput | undefined; private identityProvider: IIdentityProvider | undefined; + private nodesByIdentity = new Map>(); constructor( container: HTMLElement, delegate: IListVirtualDelegate, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], private dataSource: IDataSource, options: IDataTreeOptions = {} ) { @@ -38,6 +40,8 @@ export class DataTree extends AbstractTree extends AbstractTree { const id = this.identityProvider!.getId(element).toString(); + return viewState.expanded.indexOf(id) === -1; + }; + + const onDidCreateNode = (node: ITreeNode) => { + const id = this.identityProvider!.getId(node.element).toString(); if (viewState.focus.indexOf(id) > -1) { - focus.push(element); + focus.push(node.element); } if (viewState.selection.indexOf(id) > -1) { - selection.push(element); + selection.push(node.element); } - - return id in viewState.collapsed; }; - this._refresh(input, isCollapsed); + this._refresh(input, isCollapsed, onDidCreateNode); this.setFocus(focus); this.setSelection(selection); + + if (viewState && typeof viewState.scrollTop === 'number') { + this.scrollTop = viewState.scrollTop; + } } - refresh(element: TInput | T = this.input!): void { + updateChildren(element: TInput | T = this.input!): void { if (typeof this.input === 'undefined') { throw new Error('Tree input not set'); } - this._refresh(element); + let isCollapsed: ((el: T) => boolean | undefined) | undefined; + + if (this.identityProvider) { + isCollapsed = element => { + const id = this.identityProvider!.getId(element).toString(); + const node = this.nodesByIdentity.get(id); + + if (!node) { + return undefined; + } + + return node.collapsed; + }; + } + + this._refresh(element, isCollapsed); } - private _refresh(element: TInput | T, isCollapsed?: (el: T) => boolean): void { - this.model.setChildren((element === this.input ? null : element) as T, this.createIterator(element, isCollapsed)); + resort(element: T | TInput = this.input!, recursive = true): void { + this.model.resort((element === this.input ? null : element) as T, recursive); } - private createIterator(element: TInput | T, isCollapsed?: (el: T) => boolean): Iterator> { - const children = Iterator.fromArray(this.dataSource.getChildren(element)); + // View - return Iterator.map>(children, element => ({ - element, - children: this.createIterator(element), - collapsed: isCollapsed && isCollapsed(element) - })); + refresh(element?: T): void { + if (element === undefined) { + this.view.rerender(); + return; + } + + this.model.rerender(element); + } + + // Implementation + + private _refresh(element: TInput | T, isCollapsed?: (el: T) => boolean | undefined, onDidCreateNode?: (node: ITreeNode) => void): void { + let onDidDeleteNode: ((node: ITreeNode) => void) | undefined; + + if (this.identityProvider) { + const insertedElements = new Set(); + + const outerOnDidCreateNode = onDidCreateNode; + onDidCreateNode = (node: ITreeNode) => { + const id = this.identityProvider!.getId(node.element).toString(); + + insertedElements.add(id); + this.nodesByIdentity.set(id, node); + + if (outerOnDidCreateNode) { + outerOnDidCreateNode(node); + } + }; + + onDidDeleteNode = (node: ITreeNode) => { + const id = this.identityProvider!.getId(node.element).toString(); + + if (!insertedElements.has(id)) { + this.nodesByIdentity.delete(id); + } + }; + } + + this.model.setChildren((element === this.input ? null : element) as T, this.iterate(element, isCollapsed).elements, onDidCreateNode, onDidDeleteNode); + } + + private iterate(element: TInput | T, isCollapsed?: (el: T) => boolean | undefined): { elements: Iterator>, size: number } { + const children = this.dataSource.getChildren(element); + const elements = Iterator.map>(Iterator.fromArray(children), element => { + const { elements: children, size } = this.iterate(element, isCollapsed); + const collapsed = size === 0 ? undefined : (isCollapsed && isCollapsed(element)); + + return { element, children, collapsed }; + }); + + return { elements, size: children.length }; } protected createModel(view: ISpliceable>, options: IDataTreeOptions): ITreeModel { @@ -113,20 +184,20 @@ export class DataTree extends AbstractTree 0) { const node = queue.shift()!; - if (node !== root && node.collapsed) { - collapsed.push(getId(node.element!)); + if (node !== root && node.collapsible && !node.collapsed) { + expanded.push(getId(node.element!)); } queue.push(...node.children); } - return { focus, selection, collapsed }; + return { focus, selection, expanded, scrollTop: this.scrollTop }; } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/tree/indexTree.ts b/src/vs/base/browser/ui/tree/indexTree.ts index 180aa553b7d..b0b86e0a6f9 100644 --- a/src/vs/base/browser/ui/tree/indexTree.ts +++ b/src/vs/base/browser/ui/tree/indexTree.ts @@ -15,12 +15,12 @@ export interface IIndexTreeOptions extends IAbstractTreeO export class IndexTree extends AbstractTree { - protected model: IndexTreeModel; + protected model!: IndexTreeModel; constructor( container: HTMLElement, delegate: IListVirtualDelegate, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], private rootElement: T, options: IIndexTreeOptions = {} ) { @@ -31,7 +31,16 @@ export class IndexTree extends AbstractTree>, options: IIndexTreeOptions): ITreeModel { return new IndexTreeModel(view, this.rootElement, options); } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/tree/indexTreeModel.ts b/src/vs/base/browser/ui/tree/indexTreeModel.ts index 3df1cdee8e8..a568881e7c2 100644 --- a/src/vs/base/browser/ui/tree/indexTreeModel.ts +++ b/src/vs/base/browser/ui/tree/indexTreeModel.ts @@ -3,15 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ISpliceable } from 'vs/base/common/sequence'; -import { Iterator, ISequence } from 'vs/base/common/iterator'; -import { Emitter, Event, EventBufferer } from 'vs/base/common/event'; +import { ICollapseStateChangeEvent, ITreeElement, ITreeFilter, ITreeFilterDataResult, ITreeModel, ITreeNode, TreeVisibility, ITreeModelSpliceEvent } from 'vs/base/browser/ui/tree/tree'; import { tail2 } from 'vs/base/common/arrays'; -import { ITreeFilterDataResult, TreeVisibility, ITreeFilter, ITreeModel, ITreeNode, ITreeElement, ICollapseStateChangeEvent } from 'vs/base/browser/ui/tree/tree'; +import { Emitter, Event, EventBufferer } from 'vs/base/common/event'; +import { ISequence, Iterator } from 'vs/base/common/iterator'; +import { ISpliceable } from 'vs/base/common/sequence'; interface IMutableTreeNode extends ITreeNode { readonly parent: IMutableTreeNode | undefined; readonly children: IMutableTreeNode[]; + visibleChildrenCount: number; + visibleChildIndex: number; collapsible: boolean; collapsed: boolean; renderNodeCount: number; @@ -19,10 +21,18 @@ interface IMutableTreeNode extends ITreeNode { filterData: TFilterData | undefined; } -function isFilterResult(obj: any): obj is ITreeFilterDataResult { +export function isFilterResult(obj: any): obj is ITreeFilterDataResult { return typeof obj === 'object' && 'visibility' in obj && 'data' in obj; } +export function getVisibleState(visibility: boolean | TreeVisibility): TreeVisibility { + switch (visibility) { + case true: return TreeVisibility.Visible; + case false: return TreeVisibility.Hidden; + default: return visibility; + } +} + function treeNodeToElement(node: IMutableTreeNode): ITreeElement { const { element, collapsed } = node; const children = Iterator.map(Iterator.fromArray(node.children), treeNodeToElement); @@ -30,17 +40,10 @@ function treeNodeToElement(node: IMutableTreeNode): ITreeElement { return { element, children, collapsed }; } -function getVisibleState(visibility: boolean | TreeVisibility): TreeVisibility { - switch (visibility) { - case true: return TreeVisibility.Visible; - case false: return TreeVisibility.Hidden; - default: return visibility; - } -} - export interface IIndexTreeModelOptions { - collapseByDefault?: boolean; // defaults to false - filter?: ITreeFilter; + readonly collapseByDefault?: boolean; // defaults to false + readonly filter?: ITreeFilter; + readonly autoExpandSingleChildren?: boolean; } export class IndexTreeModel, TFilterData = void> implements ITreeModel { @@ -58,18 +61,23 @@ export class IndexTreeModel, TFilterData = voi private collapseByDefault: boolean; private filter?: ITreeFilter; + private autoExpandSingleChildren: boolean; + + private _onDidSplice = new Emitter>(); + readonly onDidSplice = this._onDidSplice.event; constructor(private list: ISpliceable>, rootElement: T, options: IIndexTreeModelOptions = {}) { this.collapseByDefault = typeof options.collapseByDefault === 'undefined' ? false : options.collapseByDefault; this.filter = options.filter; - - // this.onDidChangeCollapseState(node => console.log(node.collapsed, node)); + this.autoExpandSingleChildren = typeof options.autoExpandSingleChildren === 'undefined' ? false : options.autoExpandSingleChildren; this.root = { parent: undefined, element: rootElement, children: [], depth: 0, + visibleChildrenCount: 0, + visibleChildIndex: -1, collapsible: false, collapsed: false, renderNodeCount: 0, @@ -89,22 +97,64 @@ export class IndexTreeModel, TFilterData = voi throw new Error('Invalid tree location'); } - const { parentNode, listIndex, revealed } = this.getParentNodeWithListIndex(location); + const { parentNode, listIndex, revealed, visible } = this.getParentNodeWithListIndex(location); const treeListElementsToInsert: ITreeNode[] = []; const nodesToInsertIterator = Iterator.map(Iterator.from(toInsert), el => this.createTreeNode(el, parentNode, parentNode.visible ? TreeVisibility.Visible : TreeVisibility.Hidden, revealed, treeListElementsToInsert, onDidCreateNode)); + const lastIndex = location[location.length - 1]; + + // figure out what's the visible child start index right before the + // splice point + let visibleChildStartIndex = 0; + + for (let i = lastIndex; i >= 0 && i < parentNode.children.length; i--) { + const child = parentNode.children[i]; + + if (child.visible) { + visibleChildStartIndex = child.visibleChildIndex; + break; + } + } + const nodesToInsert: IMutableTreeNode[] = []; + let insertedVisibleChildrenCount = 0; let renderNodeCount = 0; - Iterator.forEach(nodesToInsertIterator, node => { - nodesToInsert.push(node); - renderNodeCount += node.renderNodeCount; + Iterator.forEach(nodesToInsertIterator, child => { + nodesToInsert.push(child); + renderNodeCount += child.renderNodeCount; + + if (child.visible) { + child.visibleChildIndex = visibleChildStartIndex + insertedVisibleChildrenCount++; + } }); - const lastIndex = location[location.length - 1]; const deletedNodes = parentNode.children.splice(lastIndex, deleteCount, ...nodesToInsert); - if (revealed) { + // figure out what is the count of deleted visible children + let deletedVisibleChildrenCount = 0; + + for (const child of deletedNodes) { + if (child.visible) { + deletedVisibleChildrenCount++; + } + } + + // and adjust for all visible children after the splice point + if (deletedVisibleChildrenCount !== 0) { + for (let i = lastIndex + nodesToInsert.length; i < parentNode.children.length; i++) { + const child = parentNode.children[i]; + + if (child.visible) { + child.visibleChildIndex -= deletedVisibleChildrenCount; + } + } + } + + // update parent's visible children count + parentNode.visibleChildrenCount += insertedVisibleChildrenCount - deletedVisibleChildrenCount; + + if (revealed && visible) { const visibleDeleteCount = deletedNodes.reduce((r, node) => r + node.renderNodeCount, 0); this._updateAncestorsRenderNodeCount(parentNode, renderNodeCount - visibleDeleteCount); @@ -120,11 +170,30 @@ export class IndexTreeModel, TFilterData = voi deletedNodes.forEach(visit); } - return Iterator.map(Iterator.fromArray(deletedNodes), treeNodeToElement); + const result = Iterator.map(Iterator.fromArray(deletedNodes), treeNodeToElement); + this._onDidSplice.fire({ insertedNodes: nodesToInsert, deletedNodes }); + return result; + } + + rerender(location: number[]): void { + if (location.length === 0) { + throw new Error('Invalid tree location'); + } + + const { node, listIndex, revealed } = this.getTreeNodeWithListIndex(location); + + if (revealed) { + this.list.splice(listIndex, 1, [node]); + } } getListIndex(location: number[]): number { - return this.getTreeNodeWithListIndex(location).listIndex; + const { listIndex, visible, revealed } = this.getTreeNodeWithListIndex(location); + return visible && revealed ? listIndex : -1; + } + + getListRenderCount(location: number[]): number { + return this.getTreeNode(location).renderNodeCount; } isCollapsible(location: number[]): boolean { @@ -136,18 +205,45 @@ export class IndexTreeModel, TFilterData = voi } setCollapsed(location: number[], collapsed?: boolean, recursive?: boolean): boolean { - const { node, listIndex, revealed } = this.getTreeNodeWithListIndex(location); + const node = this.getTreeNode(location); if (typeof collapsed === 'undefined') { collapsed = !node.collapsed; } - return this.eventBufferer.bufferEvents(() => { - return this._setCollapsed(node, listIndex, revealed, collapsed!, recursive || false); - }); + return this.eventBufferer.bufferEvents(() => this._setCollapsed(location, collapsed!, recursive)); } - private _setCollapsed(node: IMutableTreeNode, listIndex: number, revealed: boolean, collapsed: boolean, recursive: boolean): boolean { + private _setCollapsed(location: number[], collapsed: boolean, recursive?: boolean): boolean { + const { node, listIndex, revealed } = this.getTreeNodeWithListIndex(location); + + const result = this._setListNodeCollapsed(node, listIndex, revealed, collapsed!, recursive || false); + + if (this.autoExpandSingleChildren && !collapsed! && !recursive) { + let onlyVisibleChildIndex = -1; + + for (let i = 0; i < node.children.length; i++) { + const child = node.children[i]; + + if (child.visible) { + if (onlyVisibleChildIndex > -1) { + onlyVisibleChildIndex = -1; + break; + } else { + onlyVisibleChildIndex = i; + } + } + } + + if (onlyVisibleChildIndex > -1) { + this._setCollapsed([...location, onlyVisibleChildIndex], false, false); + } + } + + return result; + } + + private _setListNodeCollapsed(node: IMutableTreeNode, listIndex: number, revealed: boolean, collapsed: boolean, recursive: boolean): boolean { const result = this._setNodeCollapsed(node, collapsed, recursive, false); if (!revealed || !node.visible) { @@ -182,6 +278,21 @@ export class IndexTreeModel, TFilterData = voi return result; } + expandTo(location: number[]): void { + this.eventBufferer.bufferEvents(() => { + let node = this.getTreeNode(location); + + while (node.parent) { + node = node.parent; + location = location.slice(0, location.length - 1); + + if (node.collapsed) { + this._setCollapsed(location, false); + } + } + }); + } + refilter(): void { const previousRenderNodeCount = this.root.renderNodeCount; const toInsert = this.updateNodeAfterFilterChange(this.root); @@ -201,6 +312,8 @@ export class IndexTreeModel, TFilterData = voi element: treeElement.element, children: [], depth: parent.depth + 1, + visibleChildrenCount: 0, + visibleChildIndex: -1, collapsible: typeof treeElement.collapsible === 'boolean' ? treeElement.collapsible : (typeof treeElement.collapsed !== 'undefined'), collapsed: typeof treeElement.collapsed === 'undefined' ? this.collapseByDefault : treeElement.collapsed, renderNodeCount: 1, @@ -218,17 +331,21 @@ export class IndexTreeModel, TFilterData = voi const childRevealed = revealed && visibility !== TreeVisibility.Hidden && !node.collapsed; const childNodes = Iterator.map(childElements, el => this.createTreeNode(el, node, visibility, childRevealed, treeListElements, onDidCreateNode)); - let hasVisibleDescendants = false; + let visibleChildrenCount = 0; let renderNodeCount = 1; Iterator.forEach(childNodes, child => { node.children.push(child); - hasVisibleDescendants = hasVisibleDescendants || child.visible; renderNodeCount += child.renderNodeCount; + + if (child.visible) { + child.visibleChildIndex = visibleChildrenCount++; + } }); node.collapsible = node.collapsible || node.children.length > 0; - node.visible = visibility === TreeVisibility.Recurse ? hasVisibleDescendants : (visibility === TreeVisibility.Visible); + node.visibleChildrenCount = visibleChildrenCount; + node.visible = visibility === TreeVisibility.Recurse ? visibleChildrenCount > 0 : (visibility === TreeVisibility.Visible); if (!node.visible) { node.renderNodeCount = 0; @@ -306,9 +423,19 @@ export class IndexTreeModel, TFilterData = voi let hasVisibleDescendants = false; if (!node.collapsed || visibility! !== TreeVisibility.Hidden) { + let visibleChildIndex = 0; + for (const child of node.children) { hasVisibleDescendants = this._updateNodeAfterFilterChange(child, visibility!, result, revealed && !node.collapsed) || hasVisibleDescendants; + + if (child.visible) { + child.visibleChildIndex = visibleChildIndex++; + } } + + node.visibleChildrenCount = visibleChildIndex; + } else { + node.visibleChildrenCount = 0; } if (node !== this.root) { @@ -372,12 +499,12 @@ export class IndexTreeModel, TFilterData = voi } // expensive - private getTreeNodeWithListIndex(location: number[]): { node: IMutableTreeNode, listIndex: number, revealed: boolean } { + private getTreeNodeWithListIndex(location: number[]): { node: IMutableTreeNode, listIndex: number, revealed: boolean, visible: boolean } { if (location.length === 0) { - return { node: this.root, listIndex: -1, revealed: true }; + return { node: this.root, listIndex: -1, revealed: true, visible: false }; } - const { parentNode, listIndex, revealed } = this.getParentNodeWithListIndex(location); + const { parentNode, listIndex, revealed, visible } = this.getParentNodeWithListIndex(location); const index = location[location.length - 1]; if (index < 0 || index > parentNode.children.length) { @@ -386,10 +513,10 @@ export class IndexTreeModel, TFilterData = voi const node = parentNode.children[index]; - return { node, listIndex, revealed }; + return { node, listIndex, revealed, visible: visible && node.visible }; } - private getParentNodeWithListIndex(location: number[], node: IMutableTreeNode = this.root, listIndex: number = 0, revealed = true): { parentNode: IMutableTreeNode; listIndex: number; revealed: boolean; } { + private getParentNodeWithListIndex(location: number[], node: IMutableTreeNode = this.root, listIndex: number = 0, revealed = true, visible = true): { parentNode: IMutableTreeNode; listIndex: number; revealed: boolean; visible: boolean; } { const [index, ...rest] = location; if (index < 0 || index > node.children.length) { @@ -402,12 +529,13 @@ export class IndexTreeModel, TFilterData = voi } revealed = revealed && !node.collapsed; + visible = visible && node.visible; if (rest.length === 0) { - return { parentNode: node, listIndex, revealed }; + return { parentNode: node, listIndex, revealed, visible }; } - return this.getParentNodeWithListIndex(rest, node.children[index], listIndex + 1, revealed); + return this.getParentNodeWithListIndex(rest, node.children[index], listIndex + 1, revealed, visible); } getNode(location: number[] = []): ITreeNode { @@ -467,4 +595,4 @@ export class IndexTreeModel, TFilterData = voi return this._getLastElementAncestor(node.children[node.children.length - 1]); } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/tree/media/collapsed-hc.svg b/src/vs/base/browser/ui/tree/media/collapsed-hc.svg deleted file mode 100644 index 145c763338f..00000000000 --- a/src/vs/base/browser/ui/tree/media/collapsed-hc.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/tree/media/expanded-hc.svg b/src/vs/base/browser/ui/tree/media/expanded-hc.svg deleted file mode 100644 index d38d4abc89e..00000000000 --- a/src/vs/base/browser/ui/tree/media/expanded-hc.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/tree/media/tree-collapsed-dark.svg b/src/vs/base/browser/ui/tree/media/tree-collapsed-dark.svg new file mode 100644 index 00000000000..c2c2298dd5c --- /dev/null +++ b/src/vs/base/browser/ui/tree/media/tree-collapsed-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/tree/media/tree-collapsed-hc.svg b/src/vs/base/browser/ui/tree/media/tree-collapsed-hc.svg new file mode 100644 index 00000000000..3732cbc04b8 --- /dev/null +++ b/src/vs/base/browser/ui/tree/media/tree-collapsed-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/tree/media/tree-collapsed-light.svg b/src/vs/base/browser/ui/tree/media/tree-collapsed-light.svg new file mode 100644 index 00000000000..1952ad63f84 --- /dev/null +++ b/src/vs/base/browser/ui/tree/media/tree-collapsed-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/tree/media/tree-expanded-dark.svg b/src/vs/base/browser/ui/tree/media/tree-expanded-dark.svg new file mode 100644 index 00000000000..5570923e175 --- /dev/null +++ b/src/vs/base/browser/ui/tree/media/tree-expanded-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/tree/media/tree-expanded-hc.svg b/src/vs/base/browser/ui/tree/media/tree-expanded-hc.svg new file mode 100644 index 00000000000..b370009330c --- /dev/null +++ b/src/vs/base/browser/ui/tree/media/tree-expanded-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/tree/media/tree-expanded-light.svg b/src/vs/base/browser/ui/tree/media/tree-expanded-light.svg new file mode 100644 index 00000000000..939ebc8b969 --- /dev/null +++ b/src/vs/base/browser/ui/tree/media/tree-expanded-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/browser/ui/tree/media/tree.css b/src/vs/base/browser/ui/tree/media/tree.css index 3874c8d7a11..47c1e405b96 100644 --- a/src/vs/base/browser/ui/tree/media/tree.css +++ b/src/vs/base/browser/ui/tree/media/tree.css @@ -7,6 +7,30 @@ display: flex; height: 100%; align-items: center; + position: relative; +} + +.monaco-tl-indent { + height: 100%; + position: absolute; + top: 0; + left: 18px; + pointer-events: none; +} + +.hide-arrows .monaco-tl-indent { + left: 12px; +} + +.monaco-tl-indent > .indent-guide { + display: inline-block; + box-sizing: border-box; + height: 100%; + border-left: 1px solid transparent; +} + +.monaco-tl-indent > .indent-guide { + transition: border-color 0.1s linear; } .monaco-tl-twistie, @@ -19,6 +43,7 @@ text-align: right; margin-right: 6px; flex-shrink: 0; + width: 16px; } .monaco-tl-contents { @@ -28,34 +53,35 @@ .monaco-tl-twistie.collapsible { background-size: 16px; - background-position: 100% 50%; + background-position: 3px 50%; background-repeat: no-repeat; - background-image: url("expanded.svg"); + background-image: url("tree-expanded-light.svg"); } .monaco-tl-twistie.collapsible.collapsed:not(.loading) { display: inline-block; - background-image: url("collapsed.svg"); + background-image: url("tree-collapsed-light.svg"); } .vs-dark .monaco-tl-twistie.collapsible:not(.loading) { - background-image: url("expanded-dark.svg"); + background-image: url("tree-expanded-dark.svg"); } .vs-dark .monaco-tl-twistie.collapsible.collapsed:not(.loading) { - background-image: url("collapsed-dark.svg"); + background-image: url("tree-collapsed-dark.svg"); } .hc-black .monaco-tl-twistie.collapsible:not(.loading) { - background-image: url("expanded-hc.svg"); + background-image: url("tree-expanded-hc.svg"); } .hc-black .monaco-tl-twistie.collapsible.collapsed:not(.loading) { - background-image: url("collapsed-hc.svg"); + background-image: url("tree-collapsed-hc.svg"); } .monaco-tl-twistie.loading { background-image: url("loading.svg"); + background-position: 0 center; } .vs-dark .monaco-tl-twistie.loading { @@ -64,4 +90,4 @@ .hc-black .monaco-tl-twistie.loading { background-image: url("loading-hc.svg"); -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/tree/objectTree.ts b/src/vs/base/browser/ui/tree/objectTree.ts index c13063997ee..25397807106 100644 --- a/src/vs/base/browser/ui/tree/objectTree.ts +++ b/src/vs/base/browser/ui/tree/objectTree.ts @@ -6,9 +6,10 @@ import { Iterator, ISequence } from 'vs/base/common/iterator'; import { AbstractTree, IAbstractTreeOptions } from 'vs/base/browser/ui/tree/abstractTree'; import { ISpliceable } from 'vs/base/common/sequence'; -import { ITreeNode, ITreeModel, ITreeElement, ITreeRenderer, ITreeSorter } from 'vs/base/browser/ui/tree/tree'; -import { ObjectTreeModel } from 'vs/base/browser/ui/tree/objectTreeModel'; +import { ITreeNode, ITreeModel, ITreeElement, ITreeRenderer, ITreeSorter, ICollapseStateChangeEvent } from 'vs/base/browser/ui/tree/tree'; +import { ObjectTreeModel, IObjectTreeModel } from 'vs/base/browser/ui/tree/objectTreeModel'; import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { Event } from 'vs/base/common/event'; export interface IObjectTreeOptions extends IAbstractTreeOptions { sorter?: ITreeSorter; @@ -16,12 +17,14 @@ export interface IObjectTreeOptions extends IAbstractTree export class ObjectTree, TFilterData = void> extends AbstractTree { - protected model: ObjectTreeModel; + protected model!: IObjectTreeModel; + + get onDidChangeCollapseState(): Event> { return this.model.onDidChangeCollapseState; } constructor( container: HTMLElement, delegate: IListVirtualDelegate, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], options: IObjectTreeOptions = {} ) { super(container, delegate, renderers, options); @@ -29,14 +32,25 @@ export class ObjectTree, TFilterData = void> extends setChildren( element: T | null, - children?: ISequence>, - onDidCreateNode?: (node: ITreeNode) => void, - onDidDeleteNode?: (node: ITreeNode) => void + children?: ISequence> ): Iterator> { - return this.model.setChildren(element, children, onDidCreateNode, onDidDeleteNode); + return this.model.setChildren(element, children); + } + + rerender(element?: T): void { + if (element === undefined) { + this.view.rerender(); + return; + } + + this.model.rerender(element); + } + + resort(element: T, recursive = true): void { + this.model.resort(element, recursive); } protected createModel(view: ISpliceable>, options: IObjectTreeOptions): ITreeModel { return new ObjectTreeModel(view, options); } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/tree/objectTreeModel.ts b/src/vs/base/browser/ui/tree/objectTreeModel.ts index c8cc6dbc253..626d1264daa 100644 --- a/src/vs/base/browser/ui/tree/objectTreeModel.ts +++ b/src/vs/base/browser/ui/tree/objectTreeModel.ts @@ -7,20 +7,32 @@ import { ISpliceable } from 'vs/base/common/sequence'; import { Iterator, ISequence, getSequenceIterator } from 'vs/base/common/iterator'; import { IndexTreeModel, IIndexTreeModelOptions } from 'vs/base/browser/ui/tree/indexTreeModel'; import { Event } from 'vs/base/common/event'; -import { ITreeModel, ITreeNode, ITreeElement, ITreeSorter, ICollapseStateChangeEvent } from 'vs/base/browser/ui/tree/tree'; +import { ITreeModel, ITreeNode, ITreeElement, ITreeSorter, ICollapseStateChangeEvent, ITreeModelSpliceEvent } from 'vs/base/browser/ui/tree/tree'; +import { IIdentityProvider } from 'vs/base/browser/ui/list/list'; -export interface IObjectTreeModelOptions extends IIndexTreeModelOptions { - sorter?: ITreeSorter; +export type ITreeNodeCallback = (node: ITreeNode) => void; + +export interface IObjectTreeModel, TFilterData extends NonNullable = void> extends ITreeModel { + setChildren(element: T | null, children: ISequence> | undefined): Iterator>; + resort(element?: T | null, recursive?: boolean): void; } -export class ObjectTreeModel, TFilterData extends NonNullable = void> implements ITreeModel { +export interface IObjectTreeModelOptions extends IIndexTreeModelOptions { + readonly sorter?: ITreeSorter; + readonly identityProvider?: IIdentityProvider; +} + +export class ObjectTreeModel, TFilterData extends NonNullable = void> implements IObjectTreeModel { readonly rootRef = null; private model: IndexTreeModel; private nodes = new Map>(); - private sorter?: ITreeSorter>; + private readonly nodesByIdentity = new Map>(); + private readonly identityProvider?: IIdentityProvider; + private sorter?: ITreeSorter<{ element: T; }>; + readonly onDidSplice: Event>; readonly onDidChangeCollapseState: Event>; readonly onDidChangeRenderNodeCount: Event>; @@ -28,6 +40,7 @@ export class ObjectTreeModel, TFilterData extends Non constructor(list: ISpliceable>, options: IObjectTreeModelOptions = {}) { this.model = new IndexTreeModel(list, null, options); + this.onDidSplice = this.model.onDidSplice; this.onDidChangeCollapseState = this.model.onDidChangeCollapseState as Event>; this.onDidChangeRenderNodeCount = this.model.onDidChangeRenderNodeCount as Event>; @@ -38,21 +51,39 @@ export class ObjectTreeModel, TFilterData extends Non } }; } + + this.identityProvider = options.identityProvider; } setChildren( element: T | null, children: ISequence> | undefined, - onDidCreateNode?: (node: ITreeNode) => void, - onDidDeleteNode?: (node: ITreeNode) => void - ): Iterator> { + onDidCreateNode?: ITreeNodeCallback, + onDidDeleteNode?: ITreeNodeCallback + ): Iterator> { const location = this.getElementLocation(element); + return this._setChildren(location, this.preserveCollapseState(children), onDidCreateNode, onDidDeleteNode); + } + + private _setChildren( + location: number[], + children: ISequence> | undefined, + onDidCreateNode?: ITreeNodeCallback, + onDidDeleteNode?: ITreeNodeCallback + ): Iterator> { const insertedElements = new Set(); + const insertedElementIds = new Set(); const _onDidCreateNode = (node: ITreeNode) => { insertedElements.add(node.element); this.nodes.set(node.element, node); + if (this.identityProvider) { + const id = this.identityProvider.getId(node.element).toString(); + insertedElementIds.add(id); + this.nodesByIdentity.set(id, node); + } + if (onDidCreateNode) { onDidCreateNode(node); } @@ -63,21 +94,30 @@ export class ObjectTreeModel, TFilterData extends Non this.nodes.delete(node.element); } + if (this.identityProvider) { + const id = this.identityProvider.getId(node.element).toString(); + if (!insertedElementIds.has(id)) { + this.nodesByIdentity.delete(id); + } + } + if (onDidDeleteNode) { onDidDeleteNode(node); } }; - return this.model.splice( + const result = this.model.splice( [...location, 0], Number.MAX_VALUE, - this.preserveCollapseState(children), + children, _onDidCreateNode, _onDidDeleteNode ); + + return result as Iterator>; } - private preserveCollapseState(elements: ISequence> | undefined): ISequence> { + private preserveCollapseState(elements: ISequence> | undefined): ISequence> { let iterator = elements ? getSequenceIterator(elements) : Iterator.empty>(); if (this.sorter) { @@ -85,14 +125,22 @@ export class ObjectTreeModel, TFilterData extends Non } return Iterator.map(iterator, treeElement => { - const node = this.nodes.get(treeElement.element); + let node = this.nodes.get(treeElement.element); + + if (!node && this.identityProvider) { + const id = this.identityProvider.getId(treeElement.element).toString(); + node = this.nodesByIdentity.get(id); + } if (!node) { - return treeElement; + return { + ...treeElement, + children: this.preserveCollapseState(treeElement.children) + }; } const collapsible = typeof treeElement.collapsible === 'boolean' ? treeElement.collapsible : node.collapsible; - const collapsed = typeof treeElement.collapsed !== 'undefined' ? treeElement.collapsed : (collapsible && node.collapsed); + const collapsed = typeof treeElement.collapsed !== 'undefined' ? treeElement.collapsed : node.collapsed; return { ...treeElement, @@ -103,6 +151,37 @@ export class ObjectTreeModel, TFilterData extends Non }); } + rerender(element: T | null): void { + const location = this.getElementLocation(element); + this.model.rerender(location); + } + + resort(element: T | null = null, recursive = true): void { + if (!this.sorter) { + return; + } + + const location = this.getElementLocation(element); + const node = this.model.getNode(location); + + this._setChildren(location, this.resortChildren(node, recursive)); + } + + private resortChildren(node: ITreeNode, recursive: boolean, first = true): ISequence> { + let childrenNodes = Iterator.fromArray(node.children as ITreeNode[]); + + if (recursive || first) { + childrenNodes = Iterator.fromArray(Iterator.collect(childrenNodes).sort(this.sorter!.compare.bind(this.sorter))); + } + + return Iterator.map, ITreeElement>(childrenNodes, node => ({ + element: node.element as T, + collapsible: node.collapsible, + collapsed: node.collapsed, + children: this.resortChildren(node, recursive, false) + })); + } + getParentElement(ref: T | null = null): T | null { const location = this.getElementLocation(ref); return this.model.getParentElement(location); @@ -118,40 +197,63 @@ export class ObjectTreeModel, TFilterData extends Non return this.model.getLastElementAncestor(location); } - getListIndex(element: T): number { + getListIndex(element: T | null): number { const location = this.getElementLocation(element); return this.model.getListIndex(location); } - isCollapsible(element: T): boolean { + getListRenderCount(element: T | null): number { + const location = this.getElementLocation(element); + return this.model.getListRenderCount(location); + } + + isCollapsible(element: T | null): boolean { const location = this.getElementLocation(element); return this.model.isCollapsible(location); } - isCollapsed(element: T): boolean { + isCollapsed(element: T | null): boolean { const location = this.getElementLocation(element); return this.model.isCollapsed(location); } - setCollapsed(element: T, collapsed?: boolean, recursive?: boolean): boolean { + setCollapsed(element: T | null, collapsed?: boolean, recursive?: boolean): boolean { const location = this.getElementLocation(element); return this.model.setCollapsed(location, collapsed, recursive); } + expandTo(element: T | null): void { + const location = this.getElementLocation(element); + this.model.expandTo(location); + } + refilter(): void { this.model.refilter(); } getNode(element: T | null = null): ITreeNode { - const location = this.getElementLocation(element); - return this.model.getNode(location); + if (element === null) { + return this.model.getNode(this.model.rootRef); + } + + const node = this.nodes.get(element); + + if (!node) { + throw new Error(`Tree element not found: ${element}`); + } + + return node; } - getNodeLocation(node: ITreeNode): T { + getNodeLocation(node: ITreeNode): T | null { return node.element; } - getParentNodeLocation(element: T): T | null { + getParentNodeLocation(element: T | null): T | null { + if (element === null) { + throw new Error(`Invalid getParentNodeLocation call`); + } + const node = this.nodes.get(element); if (!node) { diff --git a/src/vs/base/browser/ui/tree/tree.ts b/src/vs/base/browser/ui/tree/tree.ts index baa51afa25d..5f9f2e14d69 100644 --- a/src/vs/base/browser/ui/tree/tree.ts +++ b/src/vs/base/browser/ui/tree/tree.ts @@ -5,7 +5,8 @@ import { Event } from 'vs/base/common/event'; import { Iterator } from 'vs/base/common/iterator'; -import { IListRenderer, AbstractListRenderer } from 'vs/base/browser/ui/list/list'; +import { IListRenderer, IListDragOverReaction, IListDragAndDrop, ListDragOverEffect } from 'vs/base/browser/ui/list/list'; +import { IDragAndDropData } from 'vs/base/browser/dnd'; export const enum TreeVisibility { @@ -32,7 +33,7 @@ export const enum TreeVisibility { export interface ITreeFilterDataResult { /** - * Whether the node should be visibile. + * Whether the node should be visible. */ visibility: boolean | TreeVisibility; @@ -83,6 +84,8 @@ export interface ITreeNode { readonly parent: ITreeNode | undefined; readonly children: ITreeNode[]; readonly depth: number; + readonly visibleChildrenCount: number; + readonly visibleChildIndex: number; readonly collapsible: boolean; readonly collapsed: boolean; readonly visible: boolean; @@ -94,12 +97,20 @@ export interface ICollapseStateChangeEvent { deep: boolean; } +export interface ITreeModelSpliceEvent { + insertedNodes: ITreeNode[]; + deletedNodes: ITreeNode[]; +} + export interface ITreeModel { readonly rootRef: TRef; + + readonly onDidSplice: Event>; readonly onDidChangeCollapseState: Event>; readonly onDidChangeRenderNodeCount: Event>; getListIndex(location: TRef): number; + getListRenderCount(location: TRef): number; getNode(location?: TRef): ITreeNode; getNodeLocation(node: ITreeNode): TRef; getParentNodeLocation(location: TRef): TRef; @@ -111,7 +122,9 @@ export interface ITreeModel { isCollapsible(location: TRef): boolean; isCollapsed(location: TRef): boolean; setCollapsed(location: TRef, collapsed?: boolean, recursive?: boolean): boolean; + expandTo(location: TRef): void; + rerender(location: TRef): void; refilter(): void; } @@ -125,15 +138,22 @@ export interface ITreeEvent { browserEvent?: UIEvent; } +export enum TreeMouseEventTarget { + Unknown, + Twistie, + Element +} + export interface ITreeMouseEvent { browserEvent: MouseEvent; element: T | null; + target: TreeMouseEventTarget; } export interface ITreeContextMenuEvent { browserEvent: UIEvent; element: T | null; - anchor: HTMLElement | { x: number; y: number; } | undefined; + anchor: HTMLElement | { x: number; y: number; }; } export interface ITreeNavigator { @@ -154,35 +174,23 @@ export interface IAsyncDataSource { getChildren(element: TInput | T): T[] | Promise; } -/** - * Use this renderer when you want to re-render elements on account of - * an event firing. - */ -export abstract class AbstractTreeRenderer - extends AbstractListRenderer, TTemplateData> - implements ITreeRenderer { +export const enum TreeDragOverBubble { + Down, + Up +} - private elementsToNodes = new Map>(); +export interface ITreeDragOverReaction extends IListDragOverReaction { + bubble?: TreeDragOverBubble; + autoExpand?: boolean; +} - constructor(onDidChange: Event) { - super(Event.map(onDidChange, e => { - if (typeof e === 'undefined') { - return undefined; - } else if (Array.isArray(e)) { - return e.map(e => this.elementsToNodes.get(e) || null).filter(e => e !== null); - } else { - return this.elementsToNodes.get(e) || null; - } - })); - } +export const TreeDragOverReactions = { + acceptBubbleUp(): ITreeDragOverReaction { return { accept: true, bubble: TreeDragOverBubble.Up }; }, + acceptBubbleDown(autoExpand = false): ITreeDragOverReaction { return { accept: true, bubble: TreeDragOverBubble.Down, autoExpand }; }, + acceptCopyBubbleUp(): ITreeDragOverReaction { return { accept: true, bubble: TreeDragOverBubble.Up, effect: ListDragOverEffect.Copy }; }, + acceptCopyBubbleDown(autoExpand = false): ITreeDragOverReaction { return { accept: true, bubble: TreeDragOverBubble.Down, effect: ListDragOverEffect.Copy, autoExpand }; } +}; - renderElement(node: ITreeNode, index: number, templateData: TTemplateData): void { - super.renderElement(node, index, templateData); - this.elementsToNodes.set(node.element, node); - } - - disposeElement(node: ITreeNode, index: number, templateData: TTemplateData): void { - this.elementsToNodes.set(node.element, node); - super.disposeElement(node, index, templateData); - } -} \ No newline at end of file +export interface ITreeDragAndDrop extends IListDragAndDrop { + onDragOver(data: IDragAndDropData, targetElement: T | undefined, targetIndex: number | undefined, originalEvent: DragEvent): boolean | ITreeDragOverReaction; +} diff --git a/src/vs/base/browser/ui/tree/treeDefaults.ts b/src/vs/base/browser/ui/tree/treeDefaults.ts new file mode 100644 index 00000000000..03b8665cd64 --- /dev/null +++ b/src/vs/base/browser/ui/tree/treeDefaults.ts @@ -0,0 +1,25 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; +import { Action } from 'vs/base/common/actions'; +import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree'; + +export class CollapseAllAction extends Action { + + constructor(private viewer: AsyncDataTree, enabled: boolean) { + super('vs.tree.collapse', nls.localize('collapse all', "Collapse All"), 'monaco-tree-action collapse-all', enabled); + } + + public run(context?: any): Promise { + this.viewer.collapseAll(); + this.viewer.setSelection([]); + this.viewer.setFocus([]); + this.viewer.domFocus(); + this.viewer.focusFirst(); + + return Promise.resolve(); + } +} \ No newline at end of file diff --git a/src/vs/base/common/actions.ts b/src/vs/base/common/actions.ts index 2e4fbf152d0..e6e769ea897 100644 --- a/src/vs/base/common/actions.ts +++ b/src/vs/base/common/actions.ts @@ -3,17 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IDisposable, combinedDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; export interface ITelemetryData { - from?: string; - target?: string; + readonly from?: string; + readonly target?: string; [key: string]: any; } -export interface IAction extends IDisposable { +export type WorkbenchActionExecutedClassification = { + id: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + from: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; +}; + +export type WorkbenchActionExecutedEvent = { id: string; + from: string; +}; + +export interface IAction extends IDisposable { + readonly id: string; label: string; tooltip: string; class: string | undefined; @@ -25,44 +35,44 @@ export interface IAction extends IDisposable { export interface IActionRunner extends IDisposable { run(action: IAction, context?: any): Promise; - onDidRun: Event; - onDidBeforeRun: Event; + readonly onDidRun: Event; + readonly onDidBeforeRun: Event; } -export interface IActionItem { - actionRunner: IActionRunner; +export interface IActionViewItem extends IDisposable { + readonly actionRunner: IActionRunner; setActionContext(context: any): void; render(element: any /* HTMLElement */): void; isEnabled(): boolean; focus(): void; blur(): void; - dispose(): void; } export interface IActionChangeEvent { - label?: string; - tooltip?: string; - class?: string; - enabled?: boolean; - checked?: boolean; - radio?: boolean; + readonly label?: string; + readonly tooltip?: string; + readonly class?: string; + readonly enabled?: boolean; + readonly checked?: boolean; + readonly radio?: boolean; } -export class Action implements IAction { +export class Action extends Disposable implements IAction { - protected _onDidChange = new Emitter(); + protected _onDidChange = this._register(new Emitter()); readonly onDidChange: Event = this._onDidChange.event; - protected _id: string; + protected readonly _id: string; protected _label: string; - protected _tooltip: string; + protected _tooltip: string | undefined; protected _cssClass: string | undefined; - protected _enabled: boolean; - protected _checked: boolean; - protected _radio: boolean; - protected _actionCallback?: (event?: any) => Promise; + protected _enabled: boolean = true; + protected _checked: boolean = false; + protected _radio: boolean = false; + protected readonly _actionCallback?: (event?: any) => Promise; constructor(id: string, label: string = '', cssClass: string = '', enabled: boolean = true, actionCallback?: (event?: any) => Promise) { + super(); this._id = id; this._label = label; this._cssClass = cssClass; @@ -82,7 +92,7 @@ export class Action implements IAction { this._setLabel(value); } - protected _setLabel(value: string): void { + private _setLabel(value: string): void { if (this._label !== value) { this._label = value; this._onDidChange.fire({ label: value }); @@ -90,7 +100,7 @@ export class Action implements IAction { } get tooltip(): string { - return this._tooltip; + return this._tooltip || ''; } set tooltip(value: string) { @@ -171,16 +181,12 @@ export class Action implements IAction { return Promise.resolve(true); } - - dispose() { - this._onDidChange.dispose(); - } } export interface IRunEvent { - action: IAction; - result?: any; - error?: any; + readonly action: IAction; + readonly result?: any; + readonly error?: any; } export class ActionRunner extends Disposable implements IActionRunner { @@ -191,18 +197,19 @@ export class ActionRunner extends Disposable implements IActionRunner { private _onDidRun = this._register(new Emitter()); readonly onDidRun: Event = this._onDidRun.event; - run(action: IAction, context?: any): Promise { + async run(action: IAction, context?: any): Promise { if (!action.enabled) { return Promise.resolve(null); } this._onDidBeforeRun.fire({ action: action }); - return this.runAction(action, context).then((result: any) => { + try { + const result = await this.runAction(action, context); this._onDidRun.fire({ action: action, result: result }); - }, (error: any) => { + } catch (error) { this._onDidRun.fire({ action: action, error: error }); - }); + } } protected runAction(action: IAction, context?: any): Promise { @@ -216,8 +223,8 @@ export class RadioGroup extends Disposable { constructor(readonly actions: Action[]) { super(); - this._register(combinedDisposable(actions.map(action => { - return action.onDidChange(e => { + for (const action of actions) { + this._register(action.onDidChange(e => { if (e.checked && action.checked) { for (const candidate of actions) { if (candidate !== action) { @@ -225,7 +232,7 @@ export class RadioGroup extends Disposable { } } } - }); - }))); + })); + } } } diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index 07c888aa56d..7aa42597714 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -51,8 +51,8 @@ export function binarySearch(array: ReadonlyArray, key: T, comparator: (op high = array.length - 1; while (low <= high) { - let mid = ((low + high) / 2) | 0; - let comp = comparator(array[mid], key); + const mid = ((low + high) / 2) | 0; + const comp = comparator(array[mid], key); if (comp < 0) { low = mid + 1; } else if (comp > 0) { @@ -75,7 +75,7 @@ export function findFirstInSorted(array: ReadonlyArray, p: (x: T) => boole return 0; // no children } while (low < high) { - let mid = Math.floor((low + high) / 2); + const mid = Math.floor((low + high) / 2); if (p(array[mid])) { high = mid; } else { @@ -122,7 +122,7 @@ function _sort(a: T[], compare: Compare, lo: number, hi: number, aux: T[]) if (hi <= lo) { return; } - let mid = lo + ((hi - lo) / 2) | 0; + const mid = lo + ((hi - lo) / 2) | 0; _sort(a, compare, lo, mid, aux); _sort(a, compare, mid + 1, hi, aux); if (compare(a[mid], a[mid + 1]) <= 0) { @@ -295,7 +295,7 @@ function topStep(array: ReadonlyArray, compare: (a: T, b: T) => number, re /** * @returns a new array with all falsy values removed. The original array IS NOT modified. */ -export function coalesce(array: Array): T[] { +export function coalesce(array: ReadonlyArray): T[] { if (!array) { return array; } @@ -336,7 +336,9 @@ export function isFalsyOrEmpty(obj: any): boolean { /** * @returns True if the provided object is an array and has at least one element. */ -export function isNonEmptyArray(obj: ReadonlyArray | undefined | null): obj is Array { +export function isNonEmptyArray(obj: T[] | undefined | null): obj is T[]; +export function isNonEmptyArray(obj: readonly T[] | undefined | null): obj is readonly T[]; +export function isNonEmptyArray(obj: T[] | readonly T[] | undefined | null): obj is T[] | readonly T[] { return Array.isArray(obj) && obj.length > 0; } @@ -364,6 +366,18 @@ export function distinct(array: ReadonlyArray, keyFn?: (t: T) => string): }); } +export function distinctES6(array: ReadonlyArray): T[] { + const seen = new Set(); + return array.filter(element => { + if (seen.has(element)) { + return false; + } + + seen.add(element); + return true; + }); +} + export function uniqueFilter(keyFn: (t: T) => string): (t: T) => boolean { const seen: { [key: string]: boolean; } = Object.create(null); @@ -379,6 +393,18 @@ export function uniqueFilter(keyFn: (t: T) => string): (t: T) => boolean { }; } +export function lastIndex(array: ReadonlyArray, fn: (item: T) => boolean): number { + for (let i = array.length - 1; i >= 0; i--) { + const element = array[i]; + + if (fn(element)) { + return i; + } + } + + return -1; +} + export function firstIndex(array: ReadonlyArray, fn: (item: T) => boolean): number { for (let i = 0; i < array.length; i++) { const element = array[i]; @@ -392,8 +418,8 @@ export function firstIndex(array: ReadonlyArray, fn: (item: T) => boolean) } export function first(array: ReadonlyArray, fn: (item: T) => boolean, notFoundValue: T): T; -export function first(array: ReadonlyArray, fn: (item: T) => boolean): T | null; -export function first(array: ReadonlyArray, fn: (item: T) => boolean, notFoundValue: T | null = null): T | null { +export function first(array: ReadonlyArray, fn: (item: T) => boolean): T | undefined; +export function first(array: ReadonlyArray, fn: (item: T) => boolean, notFoundValue: T | undefined = undefined): T | undefined { const index = firstIndex(array, fn); return index < 0 ? notFoundValue : array[index]; } @@ -439,9 +465,9 @@ export function range(arg: number, to?: number): number[] { return result; } -export function fill(num: number, valueFn: () => T, arr: T[] = []): T[] { +export function fill(num: number, value: T, arr: T[] = []): T[] { for (let i = 0; i < num; i++) { - arr[i] = valueFn(); + arr[i] = value; } return arr; @@ -501,8 +527,8 @@ export function shuffle(array: T[], _seed?: number): void { } for (let i = array.length - 1; i > 0; i -= 1) { - let j = Math.floor(rand() * (i + 1)); - let temp = array[i]; + const j = Math.floor(rand() * (i + 1)); + const temp = array[i]; array[i] = array[j]; array[j] = temp; } @@ -548,3 +574,7 @@ export function mapArrayOrNot(items: T | T[], fn: (_: T) => U): U | U[] { items.map(fn) : fn(items); } + +export function asArray(x: T | T[]): T[] { + return Array.isArray(x) ? x : [x]; +} diff --git a/src/vs/base/common/assert.ts b/src/vs/base/common/assert.ts index 0a54ee2e51b..1e227df640e 100644 --- a/src/vs/base/common/assert.ts +++ b/src/vs/base/common/assert.ts @@ -7,7 +7,7 @@ * Throws an error with the provided message if the provided value does not evaluate to a true Javascript value. */ export function ok(value?: any, message?: string) { - if (!value || value === null) { + if (!value) { throw new Error(message ? 'Assertion failed (' + message + ')' : 'Assertion Failed'); } } diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts index edc2ad5e2db..6906e1376ec 100644 --- a/src/vs/base/common/async.ts +++ b/src/vs/base/common/async.ts @@ -6,7 +6,7 @@ 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 { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; export function isThenable(obj: any): obj is Promise { @@ -44,12 +44,21 @@ export function createCancelablePromise(callback: (token: CancellationToken) catch(reject?: ((reason: any) => TResult | Promise) | undefined | null): Promise { return this.then(undefined, reject); } + finally(onfinally?: (() => void) | undefined | null): Promise { + return promise.finally(onfinally); + } }; } +export function raceCancellation(promise: Promise, token: CancellationToken): Promise; +export function raceCancellation(promise: Promise, token: CancellationToken, defaultValue: T): Promise; +export function raceCancellation(promise: Promise, token: CancellationToken, defaultValue?: T): Promise { + return Promise.race([promise, new Promise(resolve => token.onCancellationRequested(() => resolve(defaultValue)))]); +} + export function asPromise(callback: () => T | Thenable): Promise { return new Promise((resolve, reject) => { - let item = callback(); + const item = callback(); if (isThenable(item)) { item.then(resolve, reject); } else { @@ -175,7 +184,7 @@ export class Delayer implements IDisposable { private timeout: any; private completionPromise: Promise | null; private doResolve: ((value?: any | Promise) => void) | null; - private doReject: (err: any) => void; + private doReject?: (err: any) => void; private task: ITask> | null; constructor(public defaultDelay: number) { @@ -219,7 +228,7 @@ export class Delayer implements IDisposable { this.cancelTimeout(); if (this.completionPromise) { - this.doReject(errors.canceled()); + this.doReject!(errors.canceled()); this.completionPromise = null; } } @@ -279,7 +288,7 @@ export class Barrier { private _isOpen: boolean; private _promise: Promise; - private _completePromise: (v: boolean) => void; + private _completePromise!: (v: boolean) => void; constructor() { this._isOpen = false; @@ -320,30 +329,7 @@ export function timeout(millis: number, token?: CancellationToken): CancelablePr export function disposableTimeout(handler: () => void, timeout = 0): IDisposable { const timer = setTimeout(handler, timeout); - return { - dispose() { - clearTimeout(timer); - } - }; -} - -/** - * Returns a new promise that joins the provided promise. Upon completion of - * the provided promise the provided function will always be called. This - * method is comparable to a try-finally code block. - * @param promise a promise - * @param callback a function that will be call in the success and error case. - */ -export function always(promise: Promise, callback: () => void): Promise { - function safeCallback() { - try { - callback(); - } catch (err) { - errors.onUnexpectedError(err); - } - } - promise.then(_ => safeCallback(), _ => safeCallback()); - return Promise.resolve(promise); + return toDisposable(() => clearTimeout(timer)); } export function ignoreErrors(promise: Promise): Promise { @@ -429,11 +415,11 @@ export class Limiter { this._onFinished = new Emitter(); } - public get onFinished(): Event { + get onFinished(): Event { return this._onFinished.event; } - public get size(): number { + get size(): number { return this._size; // return this.runningPromises + this.outstandingPromises.length; } @@ -469,7 +455,7 @@ export class Limiter { } } - public dispose(): void { + dispose(): void { this._onFinished.dispose(); } } @@ -489,35 +475,30 @@ export class Queue extends Limiter { * by disposing them once the queue is empty. */ export class ResourceQueue { - private queues: { [path: string]: Queue }; + private queues: Map> = new Map(); - constructor() { - this.queues = Object.create(null); - } - - public queueFor(resource: URI): Queue { + queueFor(resource: URI): Queue { const key = resource.toString(); - if (!this.queues[key]) { + if (!this.queues.has(key)) { const queue = new Queue(); queue.onFinished(() => { queue.dispose(); - delete this.queues[key]; + this.queues.delete(key); }); - this.queues[key] = queue; + this.queues.set(key, queue); } - return this.queues[key]; + return this.queues.get(key)!; } } -export class TimeoutTimer extends Disposable { +export class TimeoutTimer implements IDisposable { private _token: any; constructor(); constructor(runner: () => void, timeout: number); constructor(runner?: () => void, timeout?: number) { - super(); this._token = -1; if (typeof runner === 'function' && typeof timeout === 'number') { @@ -527,7 +508,6 @@ export class TimeoutTimer extends Disposable { dispose(): void { this.cancel(); - super.dispose(); } cancel(): void { @@ -557,18 +537,16 @@ export class TimeoutTimer extends Disposable { } } -export class IntervalTimer extends Disposable { +export class IntervalTimer implements IDisposable { private _token: any; constructor() { - super(); this._token = -1; } dispose(): void { this.cancel(); - super.dispose(); } cancel(): void { @@ -679,19 +657,6 @@ export class RunOnceWorker extends RunOnceScheduler { } } -export function nfcall(fn: Function, ...args: any[]): Promise; -export function nfcall(fn: Function, ...args: any[]): Promise; -export function nfcall(fn: Function, ...args: any[]): any { - return new Promise((c, e) => fn(...args, (err: any, result: any) => err ? e(err) : c(result))); -} - -export function ninvoke(thisArg: any, fn: Function, ...args: any[]): Promise; -export function ninvoke(thisArg: any, fn: Function, ...args: any[]): Promise; -export function ninvoke(thisArg: any, fn: Function, ...args: any[]): any { - return new Promise((resolve, reject) => fn.call(thisArg, ...args, (err: any, result: any) => err ? reject(err) : resolve(result))); -} - - //#region -- run on idle tricks ------------ export interface IdleDeadline { @@ -708,12 +673,12 @@ declare function cancelIdleCallback(handle: number): void; (function () { if (typeof requestIdleCallback !== 'function' || typeof cancelIdleCallback !== 'function') { - let dummyIdle: IdleDeadline = Object.freeze({ + const dummyIdle: IdleDeadline = Object.freeze({ didTimeout: true, timeRemaining() { return 15; } }); - runWhenIdle = (runner, timeout = 0) => { - let handle = setTimeout(() => runner(dummyIdle), timeout); + runWhenIdle = (runner) => { + const handle = setTimeout(() => runner(dummyIdle)); let disposed = false; return { dispose() { @@ -727,7 +692,7 @@ declare function cancelIdleCallback(handle: number): void; }; } else { runWhenIdle = (runner, timeout?) => { - let handle: number = requestIdleCallback(runner, typeof timeout === 'number' ? { timeout } : undefined); + const handle: number = requestIdleCallback(runner, typeof timeout === 'number' ? { timeout } : undefined); let disposed = false; return { dispose() { @@ -751,8 +716,8 @@ export class IdleValue { private readonly _executor: () => void; private readonly _handle: IDisposable; - private _didRun: boolean; - private _value: T; + private _didRun: boolean = false; + private _value?: T; private _error: any; constructor(executor: () => T) { @@ -780,8 +745,24 @@ export class IdleValue { if (this._error) { throw this._error; } - return this._value; + return this._value!; } } //#endregion + +export async function retry(task: ITask>, delay: number, retries: number): Promise { + let lastError: Error | undefined; + + for (let i = 0; i < retries; i++) { + try { + return await task(); + } catch (error) { + lastError = error; + + await timeout(delay); + } + } + + return Promise.reject(lastError); +} diff --git a/src/vs/base/common/buffer.ts b/src/vs/base/common/buffer.ts new file mode 100644 index 00000000000..99d5e5274e1 --- /dev/null +++ b/src/vs/base/common/buffer.ts @@ -0,0 +1,466 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare var Buffer: any; +export const hasBuffer = (typeof Buffer !== 'undefined'); + +let textEncoder: TextEncoder | null; +let textDecoder: TextDecoder | null; + +export class VSBuffer { + + static alloc(byteLength: number): VSBuffer { + if (hasBuffer) { + return new VSBuffer(Buffer.allocUnsafe(byteLength)); + } else { + return new VSBuffer(new Uint8Array(byteLength)); + } + } + + static wrap(actual: Uint8Array): VSBuffer { + if (hasBuffer && !(Buffer.isBuffer(actual))) { + // https://nodejs.org/dist/latest-v10.x/docs/api/buffer.html#buffer_class_method_buffer_from_arraybuffer_byteoffset_length + // Create a zero-copy Buffer wrapper around the ArrayBuffer pointed to by the Uint8Array + actual = Buffer.from(actual.buffer, actual.byteOffset, actual.byteLength); + } + return new VSBuffer(actual); + } + + static fromString(source: string): VSBuffer { + if (hasBuffer) { + return new VSBuffer(Buffer.from(source)); + } else { + if (!textEncoder) { + textEncoder = new TextEncoder(); + } + return new VSBuffer(textEncoder.encode(source)); + } + } + + static concat(buffers: VSBuffer[], totalLength?: number): VSBuffer { + if (typeof totalLength === 'undefined') { + totalLength = 0; + for (let i = 0, len = buffers.length; i < len; i++) { + totalLength += buffers[i].byteLength; + } + } + + const ret = VSBuffer.alloc(totalLength); + let offset = 0; + for (let i = 0, len = buffers.length; i < len; i++) { + const element = buffers[i]; + ret.set(element, offset); + offset += element.byteLength; + } + + return ret; + } + + readonly buffer: Uint8Array; + readonly byteLength: number; + + private constructor(buffer: Uint8Array) { + this.buffer = buffer; + this.byteLength = this.buffer.byteLength; + } + + toString(): string { + if (hasBuffer) { + return this.buffer.toString(); + } else { + if (!textDecoder) { + textDecoder = new TextDecoder(); + } + return textDecoder.decode(this.buffer); + } + } + + slice(start?: number, end?: number): VSBuffer { + // IMPORTANT: use subarray instead of slice because TypedArray#slice + // creates shallow copy and NodeBuffer#slice doesn't. The use of subarray + // ensures the same, performant, behaviour. + return new VSBuffer(this.buffer.subarray(start!/*bad lib.d.ts*/, end)); + } + + set(array: VSBuffer, offset?: number): void { + this.buffer.set(array.buffer, offset); + } + + readUInt32BE(offset: number): number { + return readUInt32BE(this.buffer, offset); + } + + writeUInt32BE(value: number, offset: number): void { + writeUInt32BE(this.buffer, value, offset); + } + + readUInt8(offset: number): number { + return readUInt8(this.buffer, offset); + } + + writeUInt8(value: number, offset: number): void { + writeUInt8(this.buffer, value, offset); + } +} + +export function readUInt32BE(source: Uint8Array, offset: number): number { + return ( + source[offset] * 2 ** 24 + + source[offset + 1] * 2 ** 16 + + source[offset + 2] * 2 ** 8 + + source[offset + 3] + ); +} + +export function writeUInt32BE(destination: Uint8Array, value: number, offset: number): void { + destination[offset + 3] = value; + value = value >>> 8; + destination[offset + 2] = value; + value = value >>> 8; + destination[offset + 1] = value; + value = value >>> 8; + destination[offset] = value; +} + +function readUInt8(source: Uint8Array, offset: number): number { + return source[offset]; +} + +function writeUInt8(destination: Uint8Array, value: number, offset: number): void { + destination[offset] = value; +} + +export interface VSBufferReadable { + + /** + * Read data from the underlying source. Will return + * null to indicate that no more data can be read. + */ + read(): VSBuffer | null; +} + +export interface ReadableStream { + + /** + * The 'data' event is emitted whenever the stream is + * relinquishing ownership of a chunk of data to a consumer. + */ + on(event: 'data', callback: (chunk: T) => void): void; + + /** + * Emitted when any error occurs. + */ + on(event: 'error', callback: (err: any) => void): 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. + */ + on(event: 'end', callback: () => void): void; + + /** + * Stops emitting any events until resume() is called. + */ + pause?(): void; + + /** + * Starts emitting events again after pause() was called. + */ + resume?(): void; + + /** + * Destroys the stream and stops emitting any event. + */ + destroy?(): void; +} + +/** + * A readable stream that sends data via VSBuffer. + */ +export interface VSBufferReadableStream extends ReadableStream { + pause(): void; + resume(): void; + destroy(): void; +} + +export function isVSBufferReadableStream(obj: any): obj is VSBufferReadableStream { + const candidate: VSBufferReadableStream = obj; + + return candidate && [candidate.on, candidate.pause, candidate.resume, candidate.destroy].every(fn => typeof fn === 'function'); +} + +/** + * Helper to fully read a VSBuffer readable into a single buffer. + */ +export function readableToBuffer(readable: VSBufferReadable): VSBuffer { + const chunks: VSBuffer[] = []; + + let chunk: VSBuffer | null; + while (chunk = readable.read()) { + chunks.push(chunk); + } + + return VSBuffer.concat(chunks); +} + +/** + * Helper to convert a buffer into a readable buffer. + */ +export function bufferToReadable(buffer: VSBuffer): VSBufferReadable { + let done = false; + + return { + read: () => { + if (done) { + return null; + } + + done = true; + + return buffer; + } + }; +} + +/** + * Helper to fully read a VSBuffer stream into a single buffer. + */ +export function streamToBuffer(stream: VSBufferReadableStream): Promise { + return new Promise((resolve, reject) => { + const chunks: VSBuffer[] = []; + + stream.on('data', chunk => chunks.push(chunk)); + stream.on('error', error => reject(error)); + stream.on('end', () => resolve(VSBuffer.concat(chunks))); + }); +} + +/** + * Helper to create a VSBufferStream from an existing VSBuffer. + */ +export function bufferToStream(buffer: VSBuffer): VSBufferReadableStream { + const stream = writeableBufferStream(); + + stream.end(buffer); + + return stream; +} + +/** + * Helper to create a VSBufferStream from a Uint8Array stream. + */ +export function toVSBufferReadableStream(stream: ReadableStream): VSBufferReadableStream { + const vsbufferStream = writeableBufferStream(); + + stream.on('data', data => vsbufferStream.write(typeof data === 'string' ? VSBuffer.fromString(data) : VSBuffer.wrap(data))); + stream.on('end', () => vsbufferStream.end()); + stream.on('error', error => vsbufferStream.error(error)); + + return vsbufferStream; +} + +/** + * Helper to create a VSBufferStream that can be pushed + * buffers to. Will only start to emit data when a listener + * is added. + */ +export function writeableBufferStream(): VSBufferWriteableStream { + return new VSBufferWriteableStreamImpl(); +} + +export interface VSBufferWriteableStream extends VSBufferReadableStream { + write(chunk: VSBuffer): void; + error(error: Error): void; + end(result?: VSBuffer | Error): void; +} + +class VSBufferWriteableStreamImpl implements VSBufferWriteableStream { + + private readonly state = { + flowing: false, + ended: false, + destroyed: false + }; + + private readonly buffer = { + data: [] as VSBuffer[], + error: [] as Error[] + }; + + private readonly listeners = { + data: [] as { (chunk: VSBuffer): void }[], + error: [] as { (error: Error): void }[], + end: [] as { (): void }[] + }; + + pause(): void { + if (this.state.destroyed) { + return; + } + + this.state.flowing = false; + } + + resume(): void { + if (this.state.destroyed) { + return; + } + + if (!this.state.flowing) { + this.state.flowing = true; + + // emit buffered events + this.flowData(); + this.flowErrors(); + this.flowEnd(); + } + } + + write(chunk: VSBuffer): void { + if (this.state.destroyed) { + return; + } + + // flowing: directly send the data to listeners + if (this.state.flowing) { + this.listeners.data.forEach(listener => listener(chunk)); + } + + // not yet flowing: buffer data until flowing + else { + this.buffer.data.push(chunk); + } + } + + error(error: Error): void { + if (this.state.destroyed) { + return; + } + + // flowing: directly send the error to listeners + if (this.state.flowing) { + this.listeners.error.forEach(listener => listener(error)); + } + + // not yet flowing: buffer errors until flowing + else { + this.buffer.error.push(error); + } + } + + end(result?: VSBuffer | Error): void { + if (this.state.destroyed) { + return; + } + + // end with data or error if provided + if (result instanceof Error) { + this.error(result); + } else if (result) { + this.write(result); + } + + // flowing: send end event to listeners + if (this.state.flowing) { + this.listeners.end.forEach(listener => listener()); + + this.destroy(); + } + + // not yet flowing: remember state + else { + this.state.ended = true; + } + } + + on(event: 'data', callback: (chunk: VSBuffer) => void): void; + on(event: 'error', callback: (err: any) => void): void; + on(event: 'end', callback: () => void): void; + on(event: 'data' | 'error' | 'end', callback: (arg0?: any) => void): void { + if (this.state.destroyed) { + return; + } + + switch (event) { + case 'data': + this.listeners.data.push(callback); + + // switch into flowing mode as soon as the first 'data' + // listener is added and we are not yet in flowing mode + this.resume(); + + break; + + case 'end': + this.listeners.end.push(callback); + + // emit 'end' event directly if we are flowing + // and the end has already been reached + // + // finish() when it went through + if (this.state.flowing && this.flowEnd()) { + this.destroy(); + } + + break; + + case 'error': + this.listeners.error.push(callback); + + // emit buffered 'error' events unless done already + // now that we know that we have at least one listener + if (this.state.flowing) { + this.flowErrors(); + } + + break; + } + } + + private flowData(): void { + if (this.buffer.data.length > 0) { + const fullDataBuffer = VSBuffer.concat(this.buffer.data); + + this.listeners.data.forEach(listener => listener(fullDataBuffer)); + + this.buffer.data.length = 0; + } + } + + private flowErrors(): void { + if (this.listeners.error.length > 0) { + for (const error of this.buffer.error) { + this.listeners.error.forEach(listener => listener(error)); + } + + this.buffer.error.length = 0; + } + } + + private flowEnd(): boolean { + if (this.state.ended) { + this.listeners.end.forEach(listener => listener()); + + return this.listeners.end.length > 0; + } + + return false; + } + + destroy(): void { + if (!this.state.destroyed) { + this.state.destroyed = true; + this.state.ended = true; + + this.buffer.data.length = 0; + this.buffer.error.length = 0; + + this.listeners.data.length = 0; + this.listeners.error.length = 0; + this.listeners.end.length = 0; + } + } +} diff --git a/src/vs/base/common/cache.ts b/src/vs/base/common/cache.ts index 42c07e4d289..bc585927f03 100644 --- a/src/vs/base/common/cache.ts +++ b/src/vs/base/common/cache.ts @@ -4,11 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; -import { always } from 'vs/base/common/async'; +import { IDisposable } from 'vs/base/common/lifecycle'; -export interface CacheResult { +export interface CacheResult extends IDisposable { promise: Promise; - dispose(): void; } export class Cache { @@ -23,7 +22,7 @@ export class Cache { const cts = new CancellationTokenSource(); const promise = this.task(cts.token); - always(promise, () => cts.dispose()); + promise.finally(() => cts.dispose()); this.result = { promise, diff --git a/src/vs/base/common/cancellation.ts b/src/vs/base/common/cancellation.ts index 39f672c9751..fb274fb941f 100644 --- a/src/vs/base/common/cancellation.ts +++ b/src/vs/base/common/cancellation.ts @@ -16,7 +16,7 @@ export interface CancellationToken { } const shortcutEvent = Object.freeze(function (callback, context?): IDisposable { - let handle = setTimeout(callback.bind(context), 0); + const handle = setTimeout(callback.bind(context), 0); return { dispose() { clearTimeout(handle); } }; } as Event); @@ -87,7 +87,12 @@ class MutableToken implements CancellationToken { export class CancellationTokenSource { - private _token: CancellationToken; + private _token?: CancellationToken = undefined; + private _parentListener?: IDisposable = undefined; + + constructor(parent?: CancellationToken) { + this._parentListener = parent && parent.onCancellationRequested(this.cancel, this); + } get token(): CancellationToken { if (!this._token) { @@ -112,6 +117,9 @@ export class CancellationTokenSource { } dispose(): void { + if (this._parentListener) { + this._parentListener.dispose(); + } if (!this._token) { // ensure to initialize with an empty token if we had none this._token = CancellationToken.None; diff --git a/src/vs/base/common/collections.ts b/src/vs/base/common/collections.ts index f5c5cf5408b..a0f6695e8ae 100644 --- a/src/vs/base/common/collections.ts +++ b/src/vs/base/common/collections.ts @@ -46,9 +46,9 @@ export function size(from: IStringDictionary | INumberDictionary): numb } export function first(from: IStringDictionary | INumberDictionary): T | undefined { - for (let key in from) { + for (const key in from) { if (hasOwnProperty.call(from, key)) { - return from[key]; + return (from as any)[key]; } } return undefined; @@ -96,4 +96,44 @@ export function fromMap(original: Map): IStringDictionary { }); } return result; +} + +export class SetMap { + + private map = new Map>(); + + add(key: K, value: V): void { + let values = this.map.get(key); + + if (!values) { + values = new Set(); + this.map.set(key, values); + } + + values.add(value); + } + + delete(key: K, value: V): void { + const values = this.map.get(key); + + if (!values) { + return; + } + + values.delete(value); + + if (values.size === 0) { + this.map.delete(key); + } + } + + forEach(key: K, fn: (value: V) => void): void { + const values = this.map.get(key); + + if (!values) { + return; + } + + values.forEach(fn); + } } \ No newline at end of file diff --git a/src/vs/base/common/color.ts b/src/vs/base/common/color.ts index f63e7aa86f1..97528a4534c 100644 --- a/src/vs/base/common/color.ts +++ b/src/vs/base/common/color.ts @@ -260,7 +260,7 @@ export class Color { } readonly rgba: RGBA; - private _hsla: HSLA; + private _hsla?: HSLA; get hsla(): HSLA { if (this._hsla) { return this._hsla; @@ -269,7 +269,7 @@ export class Color { } } - private _hsva: HSVA; + private _hsva?: HSVA; get hsva(): HSVA { if (this._hsva) { return this._hsva; @@ -293,7 +293,7 @@ export class Color { } } - equals(other: Color): boolean { + equals(other: Color | null): boolean { return !!other && RGBA.equals(this.rgba, other.rgba) && HSLA.equals(this.hsla, other.hsla) && HSVA.equals(this.hsva, other.hsva); } @@ -387,7 +387,7 @@ export class Color { const thisA = this.rgba.a; const colorA = rgba.a; - let a = thisA + colorA * (1 - thisA); + const a = thisA + colorA * (1 - thisA); if (a < 1e-6) { return Color.transparent; } @@ -608,4 +608,4 @@ export namespace Color { } } } -} \ No newline at end of file +} diff --git a/src/vs/base/common/comparers.ts b/src/vs/base/common/comparers.ts index 4a780995790..d6dbb1784f1 100644 --- a/src/vs/base/common/comparers.ts +++ b/src/vs/base/common/comparers.ts @@ -4,31 +4,29 @@ *--------------------------------------------------------------------------------------------*/ import * as strings from 'vs/base/common/strings'; -import * as paths from 'vs/base/common/paths'; +import { sep } from 'vs/base/common/path'; import { IdleValue } from 'vs/base/common/async'; -let intlFileNameCollator: IdleValue<{ collator: Intl.Collator, collatorIsNumeric: boolean }>; - -export function setFileNameComparer(collator: IdleValue<{ collator: Intl.Collator, collatorIsNumeric: boolean }>): void { - intlFileNameCollator = collator; -} +const intlFileNameCollator: IdleValue<{ collator: Intl.Collator, collatorIsNumeric: boolean }> = new IdleValue(() => { + const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }); + return { + collator: collator, + collatorIsNumeric: collator.resolvedOptions().numeric + }; +}); export function compareFileNames(one: string | null, other: string | null, caseSensitive = false): number { - if (intlFileNameCollator) { - const a = one || ''; - const b = other || ''; - const result = intlFileNameCollator.getValue().collator.compare(a, b); + const a = one || ''; + const b = other || ''; + const result = intlFileNameCollator.getValue().collator.compare(a, b); - // Using the numeric option in the collator will - // make compare(`foo1`, `foo01`) === 0. We must disambiguate. - if (intlFileNameCollator.getValue().collatorIsNumeric && result === 0 && a !== b) { - return a < b ? -1 : 1; - } - - return result; + // Using the numeric option in the collator will + // make compare(`foo1`, `foo01`) === 0. We must disambiguate. + if (intlFileNameCollator.getValue().collatorIsNumeric && result === 0 && a !== b) { + return a < b ? -1 : 1; } - return noIntlCompareFileNames(one, other, caseSensitive); + return result; } const FileNameMatch = /^(.*?)(\.([^.]*))?$/; @@ -54,46 +52,27 @@ export function noIntlCompareFileNames(one: string | null, other: string | null, } export function compareFileExtensions(one: string | null, other: string | null): number { - if (intlFileNameCollator) { - const [oneName, oneExtension] = extractNameAndExtension(one); - const [otherName, otherExtension] = extractNameAndExtension(other); + const [oneName, oneExtension] = extractNameAndExtension(one); + const [otherName, otherExtension] = extractNameAndExtension(other); - let result = intlFileNameCollator.getValue().collator.compare(oneExtension, otherExtension); + let result = intlFileNameCollator.getValue().collator.compare(oneExtension, otherExtension); - if (result === 0) { - // Using the numeric option in the collator will - // make compare(`foo1`, `foo01`) === 0. We must disambiguate. - if (intlFileNameCollator.getValue().collatorIsNumeric && oneExtension !== otherExtension) { - return oneExtension < otherExtension ? -1 : 1; - } - - // Extensions are equal, compare filenames - result = intlFileNameCollator.getValue().collator.compare(oneName, otherName); - - if (intlFileNameCollator.getValue().collatorIsNumeric && result === 0 && oneName !== otherName) { - return oneName < otherName ? -1 : 1; - } + if (result === 0) { + // Using the numeric option in the collator will + // make compare(`foo1`, `foo01`) === 0. We must disambiguate. + if (intlFileNameCollator.getValue().collatorIsNumeric && oneExtension !== otherExtension) { + return oneExtension < otherExtension ? -1 : 1; } - return result; + // Extensions are equal, compare filenames + result = intlFileNameCollator.getValue().collator.compare(oneName, otherName); + + if (intlFileNameCollator.getValue().collatorIsNumeric && result === 0 && oneName !== otherName) { + return oneName < otherName ? -1 : 1; + } } - return noIntlCompareFileExtensions(one, other); -} - -function noIntlCompareFileExtensions(one: string | null, other: string | null): number { - const [oneName, oneExtension] = extractNameAndExtension(one && one.toLowerCase()); - const [otherName, otherExtension] = extractNameAndExtension(other && other.toLowerCase()); - - if (oneExtension !== otherExtension) { - return oneExtension < otherExtension ? -1 : 1; - } - - if (oneName === otherName) { - return 0; - } - - return oneName < otherName ? -1 : 1; + return result; } function extractNameAndExtension(str?: string | null): [string, string] { @@ -116,8 +95,8 @@ function comparePathComponents(one: string, other: string, caseSensitive = false } export function comparePaths(one: string, other: string, caseSensitive = false): number { - const oneParts = one.split(paths.nativeSep); - const otherParts = other.split(paths.nativeSep); + const oneParts = one.split(sep); + const otherParts = other.split(sep); const lastOne = oneParts.length - 1; const lastOther = otherParts.length - 1; @@ -144,8 +123,8 @@ export function comparePaths(one: string, other: string, caseSensitive = false): } export function compareAnything(one: string, other: string, lookFor: string): number { - let elementAName = one.toLowerCase(); - let elementBName = other.toLowerCase(); + const elementAName = one.toLowerCase(); + const elementBName = other.toLowerCase(); // Sort prefix matches over non prefix matches const prefixCompare = compareByPrefix(one, other, lookFor); @@ -154,14 +133,14 @@ export function compareAnything(one: string, other: string, lookFor: string): nu } // Sort suffix matches over non suffix matches - let elementASuffixMatch = strings.endsWith(elementAName, lookFor); - let elementBSuffixMatch = strings.endsWith(elementBName, lookFor); + const elementASuffixMatch = strings.endsWith(elementAName, lookFor); + const elementBSuffixMatch = strings.endsWith(elementBName, lookFor); if (elementASuffixMatch !== elementBSuffixMatch) { return elementASuffixMatch ? -1 : 1; } // Understand file names - let r = compareFileNames(elementAName, elementBName); + const r = compareFileNames(elementAName, elementBName); if (r !== 0) { return r; } @@ -171,12 +150,12 @@ export function compareAnything(one: string, other: string, lookFor: string): nu } export function compareByPrefix(one: string, other: string, lookFor: string): number { - let elementAName = one.toLowerCase(); - let elementBName = other.toLowerCase(); + const elementAName = one.toLowerCase(); + const elementBName = other.toLowerCase(); // Sort prefix matches over non prefix matches - let elementAPrefixMatch = strings.startsWith(elementAName, lookFor); - let elementBPrefixMatch = strings.startsWith(elementBName, lookFor); + const elementAPrefixMatch = strings.startsWith(elementAName, lookFor); + const elementBPrefixMatch = strings.startsWith(elementBName, lookFor); if (elementAPrefixMatch !== elementBPrefixMatch) { return elementAPrefixMatch ? -1 : 1; } diff --git a/src/vs/base/node/console.ts b/src/vs/base/common/console.ts similarity index 95% rename from src/vs/base/node/console.ts rename to src/vs/base/common/console.ts index 2ac39e3d707..9b49ff985d4 100644 --- a/src/vs/base/node/console.ts +++ b/src/vs/base/common/console.ts @@ -79,7 +79,7 @@ export function getFirstFrame(arg0: IRemoteConsoleLog | string | undefined): ISt uri: URI.file(matches[1]), line: Number(matches[2]), column: Number(matches[3]) - } as IStackFrame; + }; } } @@ -131,7 +131,10 @@ export function log(entry: IRemoteConsoleLog, label: string): void { } // Log it - console[entry.severity].apply(console, consoleArgs); + if (typeof (console as any)[entry.severity] !== 'function') { + throw new Error('Unknown console method'); + } + (console as any)[entry.severity].apply(console, consoleArgs); } function color(color: string): string { diff --git a/src/vs/base/common/errorMessage.ts b/src/vs/base/common/errorMessage.ts index ddd6976f666..e3fc44bacd3 100644 --- a/src/vs/base/common/errorMessage.ts +++ b/src/vs/base/common/errorMessage.ts @@ -10,7 +10,7 @@ import * as arrays from 'vs/base/common/arrays'; function exceptionToErrorMessage(exception: any, verbose: boolean): string { if (exception.message) { if (verbose && (exception.stack || exception.stacktrace)) { - return nls.localize('stackTrace.format', "{0}: {1}", detectSystemErrorMessage(exception), exception.stack || exception.stacktrace); + return nls.localize('stackTrace.format', "{0}: {1}", detectSystemErrorMessage(exception), stackToString(exception.stack) || stackToString(exception.stacktrace)); } return detectSystemErrorMessage(exception); @@ -19,6 +19,14 @@ function exceptionToErrorMessage(exception: any, verbose: boolean): string { return nls.localize('error.defaultMessage', "An unknown error occurred. Please consult the log for more details."); } +function stackToString(stack: string[] | string | undefined): string | undefined { + if (Array.isArray(stack)) { + return stack.join('\n'); + } + + return stack; +} + function detectSystemErrorMessage(exception: any): string { // See https://nodejs.org/api/errors.html#errors_class_system_error diff --git a/src/vs/base/common/errors.ts b/src/vs/base/common/errors.ts index 15e2eb22b8b..da6f814332f 100644 --- a/src/vs/base/common/errors.ts +++ b/src/vs/base/common/errors.ts @@ -102,7 +102,7 @@ export function transformErrorForSerialization(error: any): any; export function transformErrorForSerialization(error: any): any { if (error instanceof Error) { let { name, message } = error; - let stack: string = (error).stacktrace || (error).stack; + const stack: string = (error).stacktrace || (error).stack; return { $isError: true, name, @@ -146,7 +146,7 @@ export function isPromiseCanceledError(error: any): boolean { * Returns an error that signals cancellation. */ export function canceled(): Error { - let error = new Error(canceledName); + const error = new Error(canceledName); error.name = error.message; return error; } diff --git a/src/vs/base/common/errorsWithActions.ts b/src/vs/base/common/errorsWithActions.ts index 6b77eb5c7b1..133febb8453 100644 --- a/src/vs/base/common/errorsWithActions.ts +++ b/src/vs/base/common/errorsWithActions.ts @@ -6,11 +6,11 @@ import { IAction } from 'vs/base/common/actions'; export interface IErrorOptions { - actions?: IAction[]; + actions?: ReadonlyArray; } export interface IErrorWithActions { - actions?: IAction[]; + actions?: ReadonlyArray; } export function isErrorWithActions(obj: any): obj is IErrorWithActions { diff --git a/src/vs/base/common/event.ts b/src/vs/base/common/event.ts index 486793571f9..4d43bd8c132 100644 --- a/src/vs/base/common/event.ts +++ b/src/vs/base/common/event.ts @@ -5,7 +5,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { once as onceFn } from 'vs/base/common/functional'; -import { combinedDisposable, Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable, toDisposable, combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { LinkedList } from 'vs/base/common/linkedList'; /** @@ -13,12 +13,11 @@ import { LinkedList } from 'vs/base/common/linkedList'; * can be subscribed. The event is the subscriber function itself. */ export interface Event { - (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable; + (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable; } export namespace Event { - const _disposable = { dispose() { } }; - export const None: Event = function () { return _disposable; }; + export const None: Event = () => Disposable.None; /** * Given an event, returns another event which only fires once. @@ -27,8 +26,8 @@ export namespace Event { return (listener, thisArgs = null, disposables?) => { // we need this, in case the event fires during the listener call let didFire = false; - - const result = event(e => { + let result: IDisposable; + result = event(e => { if (didFire) { return; } else if (result) { @@ -50,10 +49,10 @@ export namespace Event { /** * Given an event and a `map` function, returns another event which maps each element - * throught the mapping function. + * through the mapping function. */ export function map(event: Event, map: (i: I) => O): Event { - return (listener, thisArgs = null, disposables?) => event(i => listener.call(thisArgs, map(i)), null, disposables); + return snapshot((listener, thisArgs = null, disposables?) => event(i => listener.call(thisArgs, map(i)), null, disposables)); } /** @@ -61,7 +60,7 @@ export namespace Event { * the `each` function per each element. */ export function forEach(event: Event, each: (i: I) => void): Event { - return (listener, thisArgs = null, disposables?) => event(i => { each(i); listener.call(thisArgs, i); }, null, disposables); + return snapshot((listener, thisArgs = null, disposables?) => event(i => { each(i); listener.call(thisArgs, i); }, null, disposables)); } /** @@ -71,7 +70,7 @@ export namespace Event { export function filter(event: Event, filter: (e: T) => boolean): Event; export function filter(event: Event, filter: (e: T | R) => e is R): Event; export function filter(event: Event, filter: (e: T) => boolean): Event { - return (listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables); + return snapshot((listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables)); } /** @@ -86,15 +85,15 @@ export namespace Event { * whenever any of the provided events emit. */ export function any(...events: Event[]): Event { - return (listener, thisArgs = null, disposables?) => combinedDisposable(events.map(event => event(e => listener.call(thisArgs, e), null, disposables))); + return (listener, thisArgs = null, disposables?) => combinedDisposable(...events.map(event => event(e => listener.call(thisArgs, e), null, disposables))); } /** * Given an event and a `merge` function, returns another event which maps each element - * and the cummulative result throught the `merge` function. Similar to `map`, but with memory. + * and the cumulative result through the `merge` function. Similar to `map`, but with memory. */ - export function reduce(event: Event, merge: (last: O | undefined, event: I) => O): Event { - let output: O | undefined = undefined; + export function reduce(event: Event, merge: (last: O | undefined, event: I) => O, initial?: O): Event { + let output: O | undefined = initial; return map(event, e => { output = merge(output, e); @@ -102,6 +101,25 @@ export namespace Event { }); } + /** + * Given a chain of event processing functions (filter, map, etc), each + * function will be invoked per event & per listener. Snapshotting an event + * chain allows each function to be invoked just once per event. + */ + export function snapshot(event: Event): Event { + let listener: IDisposable; + const emitter = new Emitter({ + onFirstListenerAdd() { + listener = event(emitter.fire, emitter); + }, + onLastListenerRemove() { + listener.dispose(); + } + }); + + return emitter.event; + } + /** * Debounces the provided event, given a `merge` function. * @@ -111,7 +129,7 @@ export namespace Event { * @param leading Whether the event should fire in the leading phase of the timeout. * @param leakWarningThreshold The leak warning threshold override. */ - export function debounce(event: Event, merge: (last: T, event: T) => T, delay?: number, leading?: boolean, leakWarningThreshold?: number): Event; + export function debounce(event: Event, merge: (last: T | undefined, event: T) => T, delay?: number, leading?: boolean, leakWarningThreshold?: number): Event; export function debounce(event: Event, merge: (last: O | undefined, event: I) => O, delay?: number, leading?: boolean, leakWarningThreshold?: number): Event; export function debounce(event: Event, merge: (last: O | undefined, event: I) => O, delay: number = 100, leading = false, leakWarningThreshold?: number): Event { @@ -133,7 +151,7 @@ export namespace Event { clearTimeout(handle); handle = setTimeout(() => { - let _output = output; + const _output = output; output = undefined; handle = undefined; if (!leading || numDebouncedCalls > 1) { @@ -171,7 +189,7 @@ export namespace Event { let cache: T; return filter(event, value => { - let shouldEmit = firstCall || value !== cache; + const shouldEmit = firstCall || value !== cache; firstCall = false; cache = value; return shouldEmit; @@ -246,71 +264,47 @@ export namespace Event { return emitter.event; } - /** - * Similar to `buffer` but it buffers indefinitely and repeats - * the buffered events to every new listener. - */ - export function echo(event: Event, nextTick = false, buffer: T[] = []): Event { - buffer = buffer.slice(); - - event(e => { - buffer.push(e); - emitter.fire(e); - }); - - const flush = (listener: (e: T) => any, thisArgs?: any) => buffer.forEach(e => listener.call(thisArgs, e)); - - const emitter = new Emitter({ - onListenerDidAdd(emitter, listener: (e: T) => any, thisArgs?: any) { - if (nextTick) { - setTimeout(() => flush(listener, thisArgs)); - } else { - flush(listener, thisArgs); - } - } - }); - - return emitter.event; - } - export interface IChainableEvent { event: Event; map(fn: (i: T) => O): IChainableEvent; forEach(fn: (i: T) => void): IChainableEvent; filter(fn: (e: T) => boolean): IChainableEvent; + reduce(merge: (last: R | undefined, event: T) => R, initial?: R): IChainableEvent; latch(): IChainableEvent; - on(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable; + on(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable; once(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable; } class ChainableEvent implements IChainableEvent { - get event(): Event { return this._event; } - - constructor(private _event: Event) { } + constructor(readonly event: Event) { } map(fn: (i: T) => O): IChainableEvent { - return new ChainableEvent(map(this._event, fn)); + return new ChainableEvent(map(this.event, fn)); } forEach(fn: (i: T) => void): IChainableEvent { - return new ChainableEvent(forEach(this._event, fn)); + return new ChainableEvent(forEach(this.event, fn)); } filter(fn: (e: T) => boolean): IChainableEvent { - return new ChainableEvent(filter(this._event, fn)); + return new ChainableEvent(filter(this.event, fn)); + } + + reduce(merge: (last: R | undefined, event: T) => R, initial?: R): IChainableEvent { + return new ChainableEvent(reduce(this.event, merge, initial)); } latch(): IChainableEvent { - return new ChainableEvent(latch(this._event)); + return new ChainableEvent(latch(this.event)); } - on(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[]) { - return this._event(listener, thisArgs, disposables); + on(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[] | DisposableStore) { + return this.event(listener, thisArgs, disposables); } once(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[]) { - return once(this._event)(listener, thisArgs, disposables); + return once(this.event)(listener, thisArgs, disposables); } } @@ -332,6 +326,20 @@ export namespace Event { return result.event; } + export interface DOMEventEmitter { + addEventListener(event: string | symbol, listener: Function): void; + removeEventListener(event: string | symbol, listener: Function): void; + } + + export function fromDOMEventEmitter(emitter: DOMEventEmitter, eventName: string, map: (...args: any[]) => T = id => id): Event { + const fn = (...args: any[]) => result.fire(map(...args)); + const onFirstListenerAdd = () => emitter.addEventListener(eventName, fn); + const onLastListenerRemove = () => emitter.removeEventListener(eventName, fn); + const result = new Emitter({ onFirstListenerAdd, onLastListenerRemove }); + + return result.event; + } + export function fromPromise(promise: Promise): Event { const emitter = new Emitter(); let shouldEmit = false; @@ -367,7 +375,7 @@ export interface EmitterOptions { let _globalLeakWarningThreshold = -1; export function setGlobalLeakWarningThreshold(n: number): IDisposable { - let oldValue = _globalLeakWarningThreshold; + const oldValue = _globalLeakWarningThreshold; _globalLeakWarningThreshold = n; return { dispose() { @@ -406,8 +414,8 @@ class LeakageMonitor { if (!this._stacks) { this._stacks = new Map(); } - let stack = new Error().stack!.split('\n').slice(3).join('\n'); - let count = (this._stacks.get(stack) || 0); + const stack = new Error().stack!.split('\n').slice(3).join('\n'); + const count = (this._stacks.get(stack) || 0); this._stacks.set(stack, count + 1); this._warnCountdown -= 1; @@ -431,7 +439,7 @@ class LeakageMonitor { } return () => { - let count = (this._stacks!.get(stack) || 0); + const count = (this._stacks!.get(stack) || 0); this._stacks!.set(stack, count - 1); }; } @@ -466,7 +474,7 @@ export class Emitter { private readonly _leakageMon?: LeakageMonitor; private _disposed: boolean = false; private _event?: Event; - private _deliveryQueue: [Listener, T][]; + private _deliveryQueue?: LinkedList<[Listener, T]>; protected _listeners?: LinkedList>; constructor(options?: EmitterOptions) { @@ -482,7 +490,7 @@ export class Emitter { */ get event(): Event { if (!this._event) { - this._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]) => { + this._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => { if (!this._listeners) { this._listeners = new LinkedList(); } @@ -527,7 +535,9 @@ export class Emitter { } } }; - if (Array.isArray(disposables)) { + if (disposables instanceof DisposableStore) { + disposables.add(result); + } else if (Array.isArray(disposables)) { disposables.push(result); } @@ -548,14 +558,14 @@ export class Emitter { // the driver of this if (!this._deliveryQueue) { - this._deliveryQueue = []; + this._deliveryQueue = new LinkedList(); } for (let iter = this._listeners.iterator(), e = iter.next(); !e.done; e = iter.next()) { this._deliveryQueue.push([e.value, event]); } - while (this._deliveryQueue.length > 0) { + while (this._deliveryQueue.size > 0) { const [listener, event] = this._deliveryQueue.shift()!; try { if (typeof listener === 'function') { @@ -572,10 +582,10 @@ export class Emitter { dispose() { if (this._listeners) { - this._listeners = undefined; + this._listeners.clear(); } if (this._deliveryQueue) { - this._deliveryQueue.length = 0; + this._deliveryQueue.clear(); } if (this._leakageMon) { this._leakageMon.dispose(); @@ -584,13 +594,58 @@ export class Emitter { } } +export class PauseableEmitter extends Emitter { + + private _isPaused = 0; + private _eventQueue = new LinkedList(); + private _mergeFn?: (input: T[]) => T; + + constructor(options?: EmitterOptions & { merge?: (input: T[]) => T }) { + super(options); + this._mergeFn = options && options.merge; + } + + pause(): void { + this._isPaused++; + } + + resume(): void { + if (this._isPaused !== 0 && --this._isPaused === 0) { + if (this._mergeFn) { + // use the merge function to create a single composite + // event. make a copy in case firing pauses this emitter + const events = this._eventQueue.toArray(); + this._eventQueue.clear(); + super.fire(this._mergeFn(events)); + + } else { + // no merging, fire each event individually and test + // that this emitter isn't paused halfway through + while (!this._isPaused && this._eventQueue.size !== 0) { + super.fire(this._eventQueue.shift()!); + } + } + } + } + + fire(event: T): void { + if (this._listeners) { + if (this._isPaused !== 0) { + this._eventQueue.push(event); + } else { + super.fire(event); + } + } + } +} + export interface IWaitUntil { waitUntil(thenable: Promise): void; } export class AsyncEmitter extends Emitter { - private _asyncDeliveryQueue: [Listener, T, Promise[]][]; + private _asyncDeliveryQueue?: [Listener, T, Promise[]][]; async fireAsync(eventFn: (thenables: Promise[], listener: Function) => T): Promise { if (!this._listeners) { @@ -605,7 +660,7 @@ export class AsyncEmitter extends Emitter { } for (let iter = this._listeners.iterator(), e = iter.next(); !e.done; e = iter.next()) { - let thenables: Promise[] = []; + const thenables: Promise[] = []; this._asyncDeliveryQueue.push([e.value, eventFn(thenables, typeof e.value === 'function' ? e.value : e.value[0]), thenables]); } diff --git a/src/vs/base/common/extpath.ts b/src/vs/base/common/extpath.ts new file mode 100644 index 00000000000..8f47ac2cc5e --- /dev/null +++ b/src/vs/base/common/extpath.ts @@ -0,0 +1,285 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { isWindows } from 'vs/base/common/platform'; +import { startsWithIgnoreCase, equalsIgnoreCase, endsWith, rtrim } from 'vs/base/common/strings'; +import { CharCode } from 'vs/base/common/charCode'; +import { sep, posix, isAbsolute, join, normalize } from 'vs/base/common/path'; + +function isPathSeparator(code: number) { + return code === CharCode.Slash || code === CharCode.Backslash; +} + +/** + * Takes a Windows OS path and changes backward slashes to forward slashes. + * This should only be done for OS paths from Windows (or user provided paths potentially from Windows). + * Using it on a Linux or MaxOS path might change it. + */ +export function toSlashes(osPath: string) { + return osPath.replace(/[\\/]/g, posix.sep); +} + +/** + * Computes the _root_ this path, like `getRoot('c:\files') === c:\`, + * `getRoot('files:///files/path') === files:///`, + * or `getRoot('\\server\shares\path') === \\server\shares\` + */ +export function getRoot(path: string, sep: string = posix.sep): string { + + if (!path) { + return ''; + } + + const len = path.length; + const firstLetter = path.charCodeAt(0); + if (isPathSeparator(firstLetter)) { + if (isPathSeparator(path.charCodeAt(1))) { + // UNC candidate \\localhost\shares\ddd + // ^^^^^^^^^^^^^^^^^^^ + if (!isPathSeparator(path.charCodeAt(2))) { + let pos = 3; + const start = pos; + for (; pos < len; pos++) { + if (isPathSeparator(path.charCodeAt(pos))) { + break; + } + } + if (start !== pos && !isPathSeparator(path.charCodeAt(pos + 1))) { + pos += 1; + for (; pos < len; pos++) { + if (isPathSeparator(path.charCodeAt(pos))) { + return path.slice(0, pos + 1) // consume this separator + .replace(/[\\/]/g, sep); + } + } + } + } + } + + // /user/far + // ^ + return sep; + + } else if (isWindowsDriveLetter(firstLetter)) { + // check for windows drive letter c:\ or c: + + if (path.charCodeAt(1) === CharCode.Colon) { + if (isPathSeparator(path.charCodeAt(2))) { + // C:\fff + // ^^^ + return path.slice(0, 2) + sep; + } else { + // C: + // ^^ + return path.slice(0, 2); + } + } + } + + // check for URI + // scheme://authority/path + // ^^^^^^^^^^^^^^^^^^^ + let pos = path.indexOf('://'); + if (pos !== -1) { + pos += 3; // 3 -> "://".length + for (; pos < len; pos++) { + if (isPathSeparator(path.charCodeAt(pos))) { + return path.slice(0, pos + 1); // consume this separator + } + } + } + + return ''; +} + +/** + * Check if the path follows this pattern: `\\hostname\sharename`. + * + * @see https://msdn.microsoft.com/en-us/library/gg465305.aspx + * @return A boolean indication if the path is a UNC path, on none-windows + * always false. + */ +export function isUNC(path: string): boolean { + if (!isWindows) { + // UNC is a windows concept + return false; + } + + if (!path || path.length < 5) { + // at least \\a\b + return false; + } + + let code = path.charCodeAt(0); + if (code !== CharCode.Backslash) { + return false; + } + code = path.charCodeAt(1); + if (code !== CharCode.Backslash) { + return false; + } + let pos = 2; + const start = pos; + for (; pos < path.length; pos++) { + code = path.charCodeAt(pos); + if (code === CharCode.Backslash) { + break; + } + } + if (start === pos) { + return false; + } + code = path.charCodeAt(pos + 1); + if (isNaN(code) || code === CharCode.Backslash) { + return false; + } + return true; +} + +// Reference: https://en.wikipedia.org/wiki/Filename +const WINDOWS_INVALID_FILE_CHARS = /[\\/:\*\?"<>\|]/g; +const UNIX_INVALID_FILE_CHARS = /[\\/]/g; +const WINDOWS_FORBIDDEN_NAMES = /^(con|prn|aux|clock\$|nul|lpt[0-9]|com[0-9])$/i; +export function isValidBasename(name: string | null | undefined, isWindowsOS: boolean = isWindows): boolean { + const invalidFileChars = isWindowsOS ? WINDOWS_INVALID_FILE_CHARS : UNIX_INVALID_FILE_CHARS; + + if (!name || name.length === 0 || /^\s+$/.test(name)) { + return false; // require a name that is not just whitespace + } + + invalidFileChars.lastIndex = 0; // the holy grail of software development + if (invalidFileChars.test(name)) { + return false; // check for certain invalid file characters + } + + if (isWindowsOS && WINDOWS_FORBIDDEN_NAMES.test(name)) { + return false; // check for certain invalid file names + } + + if (name === '.' || name === '..') { + return false; // check for reserved values + } + + if (isWindowsOS && name[name.length - 1] === '.') { + return false; // Windows: file cannot end with a "." + } + + if (isWindowsOS && name.length !== name.trim().length) { + return false; // Windows: file cannot end with a whitespace + } + + if (name.length > 255) { + return false; // most file systems do not allow files > 255 length + } + + return true; +} + +export function isEqual(pathA: string, pathB: string, ignoreCase?: boolean): boolean { + const identityEquals = (pathA === pathB); + if (!ignoreCase || identityEquals) { + return identityEquals; + } + + if (!pathA || !pathB) { + return false; + } + + return equalsIgnoreCase(pathA, pathB); +} + +export function isEqualOrParent(path: string, candidate: string, ignoreCase?: boolean, separator = sep): boolean { + if (path === candidate) { + return true; + } + + if (!path || !candidate) { + return false; + } + + if (candidate.length > path.length) { + return false; + } + + if (ignoreCase) { + const beginsWith = startsWithIgnoreCase(path, candidate); + if (!beginsWith) { + return false; + } + + if (candidate.length === path.length) { + return true; // same path, different casing + } + + let sepOffset = candidate.length; + if (candidate.charAt(candidate.length - 1) === separator) { + sepOffset--; // adjust the expected sep offset in case our candidate already ends in separator character + } + + return path.charAt(sepOffset) === separator; + } + + if (candidate.charAt(candidate.length - 1) !== separator) { + candidate += separator; + } + + return path.indexOf(candidate) === 0; +} + +export function isWindowsDriveLetter(char0: number): boolean { + return char0 >= CharCode.A && char0 <= CharCode.Z || char0 >= CharCode.a && char0 <= CharCode.z; +} + +export function sanitizeFilePath(candidate: string, cwd: string): string { + + // Special case: allow to open a drive letter without trailing backslash + if (isWindows && endsWith(candidate, ':')) { + candidate += sep; + } + + // Ensure absolute + if (!isAbsolute(candidate)) { + candidate = join(cwd, candidate); + } + + // Ensure normalized + candidate = normalize(candidate); + + // Ensure no trailing slash/backslash + if (isWindows) { + candidate = rtrim(candidate, sep); + + // Special case: allow to open drive root ('C:\') + if (endsWith(candidate, ':')) { + candidate += sep; + } + + } else { + candidate = rtrim(candidate, sep); + + // Special case: allow to open root ('/') + if (!candidate) { + candidate = sep; + } + } + + return candidate; +} + +export function isRootOrDriveLetter(path: string): boolean { + const pathNormalized = normalize(path); + + if (isWindows) { + if (path.length > 3) { + return false; + } + + return isWindowsDriveLetter(pathNormalized.charCodeAt(0)) + && pathNormalized.charCodeAt(1) === CharCode.Colon + && (path.length === 2 || pathNormalized.charCodeAt(2) === CharCode.Backslash); + } + + return pathNormalized === posix.sep; +} \ No newline at end of file diff --git a/src/vs/base/common/filters.ts b/src/vs/base/common/filters.ts index 03306c56029..d01c32668ca 100644 --- a/src/vs/base/common/filters.ts +++ b/src/vs/base/common/filters.ts @@ -28,7 +28,7 @@ export interface IMatch { export function or(...filter: IFilter[]): IFilter { return function (word: string, wordToMatchAgainst: string): IMatch[] | null { for (let i = 0, len = filter.length; i < len; i++) { - let match = filter[i](word, wordToMatchAgainst); + const match = filter[i](word, wordToMatchAgainst); if (match) { return match; } @@ -64,7 +64,7 @@ function _matchesPrefix(ignoreCase: boolean, word: string, wordToMatchAgainst: s // Contiguous Substring export function matchesContiguousSubString(word: string, wordToMatchAgainst: string): IMatch[] | null { - let index = wordToMatchAgainst.toLowerCase().indexOf(word.toLowerCase()); + const index = wordToMatchAgainst.toLowerCase().indexOf(word.toLowerCase()); if (index === -1) { return null; } @@ -119,6 +119,19 @@ function isWhitespace(code: number): boolean { ); } +const wordSeparators = new Set(); +'`~!@#$%^&*()-=+[{]}\\|;:\'",.<>/?' + .split('') + .forEach(s => wordSeparators.add(s.charCodeAt(0))); + +function isWordSeparator(code: number): boolean { + return isWhitespace(code) || wordSeparators.has(code); +} + +function charactersMatch(codeA: number, codeB: number): boolean { + return (codeA === codeB) || (isWordSeparator(codeA) && isWordSeparator(codeB)); +} + function isAlphanumeric(code: number): boolean { return isLower(code) || isUpper(code) || isNumber(code); } @@ -136,7 +149,7 @@ function join(head: IMatch, tail: IMatch[]): IMatch[] { function nextAnchor(camelCaseWord: string, start: number): number { for (let i = start; i < camelCaseWord.length; i++) { - let c = camelCaseWord.charCodeAt(i); + const c = camelCaseWord.charCodeAt(i); if (isUpper(c) || isNumber(c) || (i > 0 && !isAlphanumeric(camelCaseWord.charCodeAt(i - 1)))) { return i; } @@ -184,10 +197,10 @@ function analyzeCamelCaseWord(word: string): ICamelCaseAnalysis { if (isNumber(code)) { numeric++; } } - let upperPercent = upper / word.length; - let lowerPercent = lower / word.length; - let alphaPercent = alpha / word.length; - let numericPercent = numeric / word.length; + const upperPercent = upper / word.length; + const lowerPercent = lower / word.length; + const alphaPercent = alpha / word.length; + const numericPercent = numeric / word.length; return { upperPercent, lowerPercent, alphaPercent, numericPercent }; } @@ -289,7 +302,7 @@ function _matchesWords(word: string, target: string, i: number, j: number, conti return []; } else if (j === target.length) { return null; - } else if (word[i] !== target[j]) { + } else if (!charactersMatch(word.charCodeAt(i), target.charCodeAt(j))) { return null; } else { let result: IMatch[] | null = null; @@ -307,8 +320,8 @@ function _matchesWords(word: string, target: string, i: number, j: number, conti function nextWord(word: string, start: number): number { for (let i = start; i < word.length; i++) { - let c = word.charCodeAt(i); - if (isWhitespace(c) || (i > 0 && isWhitespace(word.charCodeAt(i - 1)))) { + if (isWordSeparator(word.charCodeAt(i)) || + (i > 0 && isWordSeparator(word.charCodeAt(i - 1)))) { return i; } } @@ -334,7 +347,7 @@ export function matchesFuzzy(word: string, wordToMatchAgainst: string, enableSep } // RegExp Filter - let match = regexp.exec(wordToMatchAgainst); + const match = regexp.exec(wordToMatchAgainst); if (match) { return [{ start: match.index, end: match.index + match[0].length }]; } @@ -348,7 +361,7 @@ export function matchesFuzzy(word: string, wordToMatchAgainst: string, enableSep * powerfull than `matchesFuzzy` */ export function matchesFuzzy2(pattern: string, word: string): IMatch[] | null { - let score = fuzzyScore(pattern, pattern.toLowerCase(), 0, word, word.toLowerCase(), 0, false); + const score = fuzzyScore(pattern, pattern.toLowerCase(), 0, word, word.toLowerCase(), 0, true); return score ? createMatches(score) : null; } @@ -366,6 +379,12 @@ export function anyScore(pattern: string, lowPattern: string, _patternPos: numbe score += 1; matches += 2 ** wordPos; idx = wordPos + 1; + + } else if (matches !== 0) { + // once we have started matching things + // we need to match the remaining pattern + // characters + break; } } return [score, matches, _wordPos]; @@ -378,29 +397,24 @@ export function createMatches(score: undefined | FuzzyScore): IMatch[] { return []; } - const [, matches, wordStart] = score; + const matches = score[1].toString(2); + const wordStart = score[2]; const res: IMatch[] = []; - for (let pos = wordStart; pos < _masks.length; pos++) { - const mask = _masks[pos]; - if (mask > matches) { - break; - } else if (matches & mask) { - res.push({ start: pos, end: pos + 1 }); + for (let pos = wordStart; pos < _maxLen; pos++) { + if (matches[matches.length - (pos + 1)] === '1') { + const last = res[res.length - 1]; + if (last && last.end === pos) { + last.end = pos + 1; + } else { + res.push({ start: pos, end: pos + 1 }); + } } } return res; } -const _maxLen = 53; - -const _masks = (function () { - const result: number[] = []; - for (let pos = 0; pos < _maxLen; pos++) { - result.push(2 ** pos); - } - return result; -}()); +const _maxLen = 128; function initTable() { const table: number[][] = []; @@ -409,7 +423,7 @@ function initTable() { row.push(-i); } for (let i = 0; i <= _maxLen; i++) { - let thisRow = row.slice(0); + const thisRow = row.slice(0); thisRow[0] = -i; table.push(thisRow); } @@ -456,6 +470,7 @@ function isSeparatorAtPos(value: string, index: number): boolean { case CharCode.SingleQuote: case CharCode.DoubleQuote: case CharCode.Colon: + case CharCode.DollarSign: return true; default: return false; @@ -480,7 +495,7 @@ function isUpperCaseAtPos(pos: number, word: string, wordLow: string): boolean { return word[pos] !== wordLow[pos]; } -function isPatternInWord(patternLow: string, patternPos: number, patternLen: number, wordLow: string, wordPos: number, wordLen: number): boolean { +export function isPatternInWord(patternLow: string, patternPos: number, patternLen: number, wordLow: string, wordPos: number, wordLen: number): boolean { while (patternPos < patternLen && wordPos < wordLen) { if (patternLow[patternPos] === wordLow[wordPos]) { patternPos += 1; @@ -504,7 +519,11 @@ export namespace FuzzyScore { /** * No matches and value `-100` */ - export const Default: [-100, 0, 0] = [-100, 0, 0]; + export const Default: [-100, 0, 0] = <[-100, 0, 0]>Object.freeze([-100, 0, 0]); + + export function isDefault(score?: FuzzyScore): score is [-100, 0, 0] { + return !score || (score[0] === -100 && score[1] === 0 && score[2] === 0); + } } export interface FuzzyScorer { @@ -566,9 +585,9 @@ export function fuzzyScore(pattern: string, patternLow: string, patternPos: numb _scores[patternPos][wordPos] = score; - let diag = _table[patternPos - 1][wordPos - 1] + (score > 1 ? 1 : score); - let top = _table[patternPos - 1][wordPos] + -1; - let left = _table[patternPos][wordPos - 1] + -1; + const diag = _table[patternPos - 1][wordPos - 1] + (score > 1 ? 1 : score); + const top = _table[patternPos - 1][wordPos] + -1; + const left = _table[patternPos][wordPos - 1] + -1; if (left >= top) { // left or diag @@ -635,8 +654,8 @@ function _findAllMatches2(patternPos: number, wordPos: number, total: number, ma while (patternPos > _patternStartPos && wordPos > 0) { - let score = _scores[patternPos][wordPos]; - let arrow = _arrows[patternPos][wordPos]; + const score = _scores[patternPos][wordPos]; + const arrow = _arrows[patternPos][wordPos]; if (arrow === Arrow.Left) { // left -> no match, skip a word character @@ -733,11 +752,11 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern // permutations of the pattern to find a better match. The // permutations only swap neighbouring characters, e.g // `cnoso` becomes `conso`, `cnsoo`, `cnoos`. - let tries = Math.min(7, pattern.length - 1); + const tries = Math.min(7, pattern.length - 1); for (let movingPatternPos = patternPos + 1; movingPatternPos < tries; movingPatternPos++) { - let newPattern = nextTypoPermutation(pattern, movingPatternPos); + const newPattern = nextTypoPermutation(pattern, movingPatternPos); if (newPattern) { - let candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, firstMatchCanBeWeak); + const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, firstMatchCanBeWeak); if (candidate) { candidate[0] -= 3; // permutation penalty if (!top || candidate[0] > top[0]) { @@ -757,8 +776,8 @@ function nextTypoPermutation(pattern: string, patternPos: number): string | unde return undefined; } - let swap1 = pattern[patternPos]; - let swap2 = pattern[patternPos + 1]; + const swap1 = pattern[patternPos]; + const swap2 = pattern[patternPos + 1]; if (swap1 === swap2) { return undefined; diff --git a/src/vs/base/common/glob.ts b/src/vs/base/common/glob.ts index f9c74b9ed46..78fc5e97ce1 100644 --- a/src/vs/base/common/glob.ts +++ b/src/vs/base/common/glob.ts @@ -5,19 +5,19 @@ import * as arrays from 'vs/base/common/arrays'; import * as strings from 'vs/base/common/strings'; -import * as paths from 'vs/base/common/paths'; +import * as extpath from 'vs/base/common/extpath'; +import * as paths from 'vs/base/common/path'; import { LRUCache } from 'vs/base/common/map'; import { CharCode } from 'vs/base/common/charCode'; import { isThenable } from 'vs/base/common/async'; export interface IExpression { - [pattern: string]: boolean | SiblingClause | any; + [pattern: string]: boolean | SiblingClause; } export interface IRelativePattern { base: string; pattern: string; - pathToRelative(from: string, to: string): string; } export function getEmptyExpression(): IExpression { @@ -53,7 +53,7 @@ export function splitGlobAware(pattern: string, splitChar: string): string[] { return []; } - let segments: string[] = []; + const segments: string[] = []; let inBraces = false; let inBrackets = false; @@ -102,7 +102,7 @@ function parseRegExp(pattern: string): string { let regEx = ''; // Split up into segments for each slash found - let segments = splitGlobAware(pattern, GLOB_SPLIT); + const segments = splitGlobAware(pattern, GLOB_SPLIT); // Special case where we only have globstars if (segments.every(s => s === GLOBSTAR)) { @@ -179,10 +179,10 @@ function parseRegExp(pattern: string): string { continue; case '}': - let choices = splitGlobAware(braceVal, ','); + const choices = splitGlobAware(braceVal, ','); // Converts {foo,bar} => [foo|bar] - let braceRegExp = `(?:${choices.map(c => parseRegExp(c)).join('|')})`; + const braceRegExp = `(?:${choices.map(c => parseRegExp(c)).join('|')})`; regEx += braceRegExp; @@ -302,7 +302,7 @@ function parsePattern(arg1: string | IRelativePattern, options: IGlobOptions): P if (T1.test(pattern)) { // common pattern: **/*.txt just need endsWith check const base = pattern.substr(4); // '**/*'.length === 4 parsedPattern = function (path, basename) { - return path && strings.endsWith(path, base) ? pattern : null; + return typeof path === 'string' && strings.endsWith(path, base) ? pattern : null; }; } else if (match = T2.exec(trimForExclusions(pattern, options))) { // common pattern: **/some.txt just need basename check parsedPattern = trivia2(match[1], pattern); @@ -331,11 +331,10 @@ function wrapRelativePattern(parsedPattern: ParsedStringPattern, arg2: string | } return function (path, basename) { - if (!paths.isEqualOrParent(path, arg2.base)) { + if (!extpath.isEqualOrParent(path, arg2.base)) { return null; } - - return parsedPattern(arg2.pathToRelative(arg2.base, path), basename); + return parsedPattern(paths.relative(arg2.base, path), basename); }; } @@ -348,7 +347,7 @@ function trivia2(base: string, originalPattern: string): ParsedStringPattern { const slashBase = `/${base}`; const backslashBase = `\\${base}`; const parsedPattern: ParsedStringPattern = function (path, basename) { - if (!path) { + if (typeof path !== 'string') { return null; } if (basename) { @@ -396,12 +395,12 @@ function trivia3(pattern: string, options: IGlobOptions): ParsedStringPattern { // common patterns: **/something/else just need endsWith check, something/else just needs and equals check function trivia4and5(path: string, pattern: string, matchPathEnds: boolean): ParsedStringPattern { - const nativePath = paths.nativeSep !== paths.sep ? path.replace(ALL_FORWARD_SLASHES, paths.nativeSep) : path; - const nativePathEnd = paths.nativeSep + nativePath; + const nativePath = paths.sep !== paths.posix.sep ? path.replace(ALL_FORWARD_SLASHES, paths.sep) : path; + const nativePathEnd = paths.sep + nativePath; const parsedPattern: ParsedStringPattern = matchPathEnds ? function (path, basename) { - return path && (path === nativePath || strings.endsWith(path, nativePathEnd)) ? pattern : null; + return typeof path === 'string' && (path === nativePath || strings.endsWith(path, nativePathEnd)) ? pattern : null; } : function (path, basename) { - return path && path === nativePath ? pattern : null; + return typeof path === 'string' && path === nativePath ? pattern : null; }; parsedPattern.allPaths = [(matchPathEnds ? '*/' : './') + path]; return parsedPattern; @@ -412,7 +411,7 @@ function toRegExp(pattern: string): ParsedStringPattern { const regExp = new RegExp(`^${parseRegExp(pattern)}$`); return function (path: string, basename: string) { regExp.lastIndex = 0; // reset RegExp to its initial state to reuse it! - return path && regExp.test(path) ? pattern : null; + return typeof path === 'string' && regExp.test(path) ? pattern : null; }; } catch (error) { return NULL; @@ -429,8 +428,8 @@ function toRegExp(pattern: string): ParsedStringPattern { */ export function match(pattern: string | IRelativePattern, path: string): boolean; export function match(expression: IExpression, path: string, hasSibling?: (name: string) => boolean): string /* the matching pattern */; -export function match(arg1: string | IExpression | IRelativePattern, path: string, hasSibling?: (name: string) => boolean): any { - if (!arg1 || !path) { +export function match(arg1: string | IExpression | IRelativePattern, path: string, hasSibling?: (name: string) => boolean): boolean | string | null | Promise { + if (!arg1 || typeof path !== 'string') { return false; } @@ -447,25 +446,25 @@ export function match(arg1: string | IExpression | IRelativePattern, path: strin */ export function parse(pattern: string | IRelativePattern, options?: IGlobOptions): ParsedPattern; export function parse(expression: IExpression, options?: IGlobOptions): ParsedExpression; -export function parse(arg1: string | IExpression | IRelativePattern, options: IGlobOptions = {}): any { +export function parse(arg1: string | IExpression | IRelativePattern, options: IGlobOptions = {}): ParsedPattern | ParsedExpression { if (!arg1) { return FALSE; } // Glob with String if (typeof arg1 === 'string' || isRelativePattern(arg1)) { - const parsedPattern = parsePattern(arg1 as string | IRelativePattern, options); + const parsedPattern = parsePattern(arg1, options); if (parsedPattern === NULL) { return FALSE; } - const resultPattern = function (path: string, basename: string) { + const resultPattern: ParsedPattern & { allBasenames?: string[]; allPaths?: string[]; } = function (path: string, basename: string) { return !!parsedPattern(path, basename); }; if (parsedPattern.allBasenames) { - (resultPattern).allBasenames = parsedPattern.allBasenames; + resultPattern.allBasenames = parsedPattern.allBasenames; } if (parsedPattern.allPaths) { - (resultPattern).allPaths = parsedPattern.allPaths; + resultPattern.allPaths = parsedPattern.allPaths; } return resultPattern; } @@ -512,21 +511,10 @@ function listToMap(list: string[]) { return map; } -export function isRelativePattern(obj: any): obj is IRelativePattern { +export function isRelativePattern(obj: unknown): obj is IRelativePattern { const rp = obj as IRelativePattern; - return rp && typeof rp.base === 'string' && typeof rp.pattern === 'string' && typeof rp.pathToRelative === 'function'; -} - -/** - * Same as `parse`, but the ParsedExpression is guaranteed to return a Promise - */ -export function parseToAsync(expression: IExpression, options?: IGlobOptions): ParsedExpression { - const parsedExpression = parse(expression, options); - return (path: string, basename?: string, hasSibling?: (name: string) => boolean | Promise): string | null | Promise => { - const result = parsedExpression(path, basename, hasSibling); - return isThenable(result) ? result : Promise.resolve(result); - }; + return rp && typeof rp.base === 'string' && typeof rp.pattern === 'string'; } export function getBasenameTerms(patternOrExpression: ParsedPattern | ParsedExpression): string[] { @@ -613,7 +601,7 @@ function parsedExpression(expression: IExpression, options: IGlobOptions): Parse return resultExpression; } -function parseExpressionPattern(pattern: string, value: any, options: IGlobOptions): (ParsedStringPattern | ParsedExpressionPattern) { +function parseExpressionPattern(pattern: string, value: boolean | SiblingClause, options: IGlobOptions): (ParsedStringPattern | ParsedExpressionPattern) { if (value === false) { return NULL; // pattern is disabled } @@ -675,7 +663,7 @@ function aggregateBasenameMatches(parsedPatterns: Array[]); } const aggregate: ParsedStringPattern = function (path, basename) { - if (!path) { + if (typeof path !== 'string') { return null; } if (!basename) { diff --git a/src/vs/base/common/hash.ts b/src/vs/base/common/hash.ts index 6c0025b1d74..0a5106d3bd6 100644 --- a/src/vs/base/common/hash.ts +++ b/src/vs/base/common/hash.ts @@ -69,4 +69,4 @@ export class Hasher { this._value = hash(obj, this._value); return this._value; } -} \ No newline at end of file +} diff --git a/src/vs/base/common/history.ts b/src/vs/base/common/history.ts index 95551eb1a7a..4aa6b3216e5 100644 --- a/src/vs/base/common/history.ts +++ b/src/vs/base/common/history.ts @@ -7,9 +7,9 @@ import { INavigator, ArrayNavigator } from 'vs/base/common/iterator'; export class HistoryNavigator implements INavigator { - private _history: Set; + private _history!: Set; private _limit: number; - private _navigator: ArrayNavigator; + private _navigator!: ArrayNavigator; constructor(history: T[] = [], limit: number = 10) { this._initialize(history); @@ -66,7 +66,7 @@ export class HistoryNavigator implements INavigator { } private _reduceToLimit() { - let data = this._elements; + const data = this._elements; if (data.length > this._limit) { this._initialize(data.slice(data.length - this._limit)); } diff --git a/src/vs/base/common/htmlContent.ts b/src/vs/base/common/htmlContent.ts index def335d55d2..ac7c8ed3a91 100644 --- a/src/vs/base/common/htmlContent.ts +++ b/src/vs/base/common/htmlContent.ts @@ -16,7 +16,6 @@ export class MarkdownString implements IMarkdownString { value: string; isTrusted?: boolean; - sanitize: boolean = true; constructor(value: string = '') { this.value = value; @@ -93,3 +92,25 @@ export function removeMarkdownEscapes(text: string): string { } return text.replace(/\\([\\`*_{}[\]()#+\-.!])/g, '$1'); } + +export function parseHrefAndDimensions(href: string): { href: string, dimensions: string[] } { + const dimensions: string[] = []; + const splitted = href.split('|').map(s => s.trim()); + href = splitted[0]; + const parameters = splitted[1]; + if (parameters) { + const heightFromParams = /height=(\d+)/.exec(parameters); + const widthFromParams = /width=(\d+)/.exec(parameters); + const height = heightFromParams ? heightFromParams[1] : ''; + const width = widthFromParams ? widthFromParams[1] : ''; + const widthIsFinite = isFinite(parseInt(width)); + const heightIsFinite = isFinite(parseInt(height)); + if (widthIsFinite) { + dimensions.push(`width="${width}"`); + } + if (heightIsFinite) { + dimensions.push(`height="${height}"`); + } + } + return { href, dimensions }; +} diff --git a/src/vs/base/common/iterator.ts b/src/vs/base/common/iterator.ts index 038bf263222..db53b8aef57 100644 --- a/src/vs/base/common/iterator.ts +++ b/src/vs/base/common/iterator.ts @@ -29,6 +29,21 @@ export module Iterator { return _empty; } + export function single(value: T): Iterator { + let done = false; + + return { + next(): IteratorResult { + if (done) { + return FIN; + } + + done = true; + return { done: false, value }; + } + }; + } + export function fromArray(array: T[], index = 0, length = array.length): Iterator { return { next(): IteratorResult { @@ -86,11 +101,47 @@ export module Iterator { } } - export function collect(iterator: Iterator): T[] { + export function collect(iterator: Iterator, atMost: number = Number.POSITIVE_INFINITY): T[] { const result: T[] = []; - forEach(iterator, value => result.push(value)); + + if (atMost === 0) { + return result; + } + + let i = 0; + + for (let next = iterator.next(); !next.done; next = iterator.next()) { + result.push(next.value); + + if (++i >= atMost) { + break; + } + } + return result; } + + export function concat(...iterators: Iterator[]): Iterator { + let i = 0; + + return { + next() { + if (i >= iterators.length) { + return FIN; + } + + const iterator = iterators[i]; + const result = iterator.next(); + + if (result.done) { + i++; + return this.next(); + } + + return result; + } + }; + } } export type ISequence = Iterator | T[]; diff --git a/src/vs/base/common/json.ts b/src/vs/base/common/json.ts index 12651380219..da0535be422 100644 --- a/src/vs/base/common/json.ts +++ b/src/vs/base/common/json.ts @@ -205,11 +205,11 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON token: SyntaxKind = SyntaxKind.Unknown, scanError: ScanError = ScanError.None; - function scanHexDigits(count: number, exact?: boolean): number { + function scanHexDigits(count: number): number { let digits = 0; let value = 0; - while (digits < count || !exact) { - let ch = text.charCodeAt(pos); + while (digits < count) { + const ch = text.charCodeAt(pos); if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) { value = value * 16 + ch - CharacterCodes._0; } @@ -240,7 +240,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON } function scanNumber(): string { - let start = pos; + const start = pos; if (text.charCodeAt(pos) === CharacterCodes._0) { pos++; } else { @@ -331,7 +331,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON result += '\t'; break; case CharacterCodes.u: - let ch = scanHexDigits(4, true); + const ch = scanHexDigits(4); if (ch >= 0) { result += String.fromCharCode(ch); } else { @@ -374,12 +374,12 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON let code = text.charCodeAt(pos); // trivia: whitespace - if (isWhiteSpace(code)) { + if (isWhitespace(code)) { do { pos++; value += String.fromCharCode(code); code = text.charCodeAt(pos); - } while (isWhiteSpace(code)); + } while (isWhitespace(code)); return token = SyntaxKind.Trivia; } @@ -424,7 +424,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON // comments case CharacterCodes.slash: - let start = pos - 1; + const start = pos - 1; // Single-line comment if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; @@ -444,10 +444,10 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { pos += 2; - let safeLength = len - 1; // For lookahead. + const safeLength = len - 1; // For lookahead. let commentClosed = false; while (pos < safeLength) { - let ch = text.charCodeAt(pos); + const ch = text.charCodeAt(pos); if (ch === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; @@ -517,7 +517,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON } function isUnknownContentCharacter(code: CharacterCodes) { - if (isWhiteSpace(code) || isLineBreak(code)) { + if (isWhitespace(code) || isLineBreak(code)) { return false; } switch (code) { @@ -555,7 +555,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON }; } -function isWhiteSpace(ch: number): boolean { +function isWhitespace(ch: number): boolean { return ch === CharacterCodes.space || ch === CharacterCodes.tab || ch === CharacterCodes.verticalTab || ch === CharacterCodes.formFeed || ch === CharacterCodes.nonBreakingSpace || ch === CharacterCodes.ogham || ch >= CharacterCodes.enQuad && ch <= CharacterCodes.zeroWidthSpace || ch === CharacterCodes.narrowNoBreakSpace || ch === CharacterCodes.mathematicalSpace || ch === CharacterCodes.ideographicSpace || ch === CharacterCodes.byteOrderMark; @@ -720,8 +720,8 @@ interface NodeImpl extends Node { * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index. */ export function getLocation(text: string, position: number): Location { - let segments: Segment[] = []; // strings or numbers - let earlyReturnException = new Object(); + const segments: Segment[] = []; // strings or numbers + const earlyReturnException = new Object(); let previousNode: NodeImpl | undefined = undefined; const previousNodeInst: NodeImpl = { value: {}, @@ -800,7 +800,7 @@ export function getLocation(text: string, position: number): Location { isAtPropertyKey = false; previousNode = undefined; } else if (sep === ',') { - let last = segments[segments.length - 1]; + const last = segments[segments.length - 1]; if (typeof last === 'number') { segments[segments.length - 1] = last + 1; } else { @@ -843,7 +843,7 @@ export function getLocation(text: string, position: number): Location { export function parse(text: string, errors: ParseError[] = [], options: ParseOptions = ParseOptions.DEFAULT): any { let currentProperty: string | null = null; let currentParent: any = []; - let previousParents: any[] = []; + const previousParents: any[] = []; function onValue(value: any) { if (Array.isArray(currentParent)) { @@ -853,9 +853,9 @@ export function parse(text: string, errors: ParseError[] = [], options: ParseOpt } } - let visitor: JSONVisitor = { + const visitor: JSONVisitor = { onObjectBegin: () => { - let object = {}; + const object = {}; onValue(object); previousParents.push(currentParent); currentParent = object; @@ -868,7 +868,7 @@ export function parse(text: string, errors: ParseError[] = [], options: ParseOpt currentParent = previousParents.pop(); }, onArrayBegin: () => { - let array: any[] = []; + const array: any[] = []; onValue(array); previousParents.push(currentParent); currentParent = array; @@ -905,7 +905,7 @@ export function parseTree(text: string, errors: ParseError[] = [], options: Pars return valueNode; } - let visitor: JSONVisitor = { + const visitor: JSONVisitor = { onObjectBegin: (offset: number) => { currentParent = onValue({ type: 'object', offset, length: -1, parent: currentParent, children: [] }); }, @@ -945,7 +945,7 @@ export function parseTree(text: string, errors: ParseError[] = [], options: Pars }; visit(text, visitor, options); - let result = currentParent.children![0]; + const result = currentParent.children![0]; if (result) { delete result.parent; } @@ -977,7 +977,7 @@ export function findNodeAtLocation(root: Node, path: JSONPath): Node | undefined return undefined; } } else { - let index = segment; + const index = segment; if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) { return undefined; } @@ -994,12 +994,12 @@ export function getNodePath(node: Node): JSONPath { if (!node.parent || !node.parent.children) { return []; } - let path = getNodePath(node.parent); + const path = getNodePath(node.parent); if (node.parent.type === 'property') { - let key = node.parent.children[0].value; + const key = node.parent.children[0].value; path.push(key); } else if (node.parent.type === 'array') { - let index = node.parent.children.indexOf(node); + const index = node.parent.children.indexOf(node); if (index !== -1) { path.push(index); } @@ -1015,9 +1015,9 @@ export function getNodeValue(node: Node): any { case 'array': return node.children!.map(getNodeValue); case 'object': - let obj = Object.create(null); + const obj = Object.create(null); for (let prop of node.children!) { - let valueNode = prop.children![1]; + const valueNode = prop.children![1]; if (valueNode) { obj[prop.children![0].value] = getNodeValue(valueNode); } @@ -1043,10 +1043,10 @@ export function contains(node: Node, offset: number, includeRightBound = false): */ export function findNodeAtOffset(node: Node, offset: number, includeRightBound = false): Node | undefined { if (contains(node, offset, includeRightBound)) { - let children = node.children; + const children = node.children; if (Array.isArray(children)) { for (let i = 0; i < children.length && children[i].offset <= offset; i++) { - let item = findNodeAtOffset(children[i], offset, includeRightBound); + const item = findNodeAtOffset(children[i], offset, includeRightBound); if (item) { return item; } @@ -1064,7 +1064,7 @@ export function findNodeAtOffset(node: Node, offset: number, includeRightBound = */ export function visit(text: string, visitor: JSONVisitor, options: ParseOptions = ParseOptions.DEFAULT): any { - let _scanner = createScanner(text, false); + const _scanner = createScanner(text, false); function toNoArgVisit(visitFunction?: (offset: number, length: number) => void): () => void { return visitFunction ? () => visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true; @@ -1073,7 +1073,7 @@ export function visit(text: string, visitor: JSONVisitor, options: ParseOptions return visitFunction ? (arg: T) => visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true; } - let onObjectBegin = toNoArgVisit(visitor.onObjectBegin), + const onObjectBegin = toNoArgVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisit(visitor.onObjectProperty), onObjectEnd = toNoArgVisit(visitor.onObjectEnd), onArrayBegin = toNoArgVisit(visitor.onArrayBegin), @@ -1083,11 +1083,11 @@ export function visit(text: string, visitor: JSONVisitor, options: ParseOptions onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError); - let disallowComments = options && options.disallowComments; - let allowTrailingComma = options && options.allowTrailingComma; + const disallowComments = options && options.disallowComments; + const allowTrailingComma = options && options.allowTrailingComma; function scanNext(): SyntaxKind { while (true) { - let token = _scanner.scan(); + const token = _scanner.scan(); switch (_scanner.getTokenError()) { case ScanError.InvalidUnicode: handleError(ParseErrorCode.InvalidUnicode); @@ -1148,7 +1148,7 @@ export function visit(text: string, visitor: JSONVisitor, options: ParseOptions } function parseString(isValue: boolean): boolean { - let value = _scanner.getTokenValue(); + const value = _scanner.getTokenValue(); if (isValue) { onLiteralValue(value); } else { diff --git a/src/vs/base/common/jsonEdit.ts b/src/vs/base/common/jsonEdit.ts index 7675ea16049..a1538870749 100644 --- a/src/vs/base/common/jsonEdit.ts +++ b/src/vs/base/common/jsonEdit.ts @@ -5,6 +5,7 @@ import { ParseError, Node, JSONPath, Segment, parseTree, findNodeAtLocation } from './json'; import { Edit, format, isEOL, FormattingOptions } from './jsonFormatter'; +import { mergeSort } from 'vs/base/common/arrays'; export function removeProperty(text: string, path: JSONPath, formattingOptions: FormattingOptions): Edit[] { @@ -12,9 +13,9 @@ export function removeProperty(text: string, path: JSONPath, formattingOptions: } export function setProperty(text: string, originalPath: JSONPath, value: any, formattingOptions: FormattingOptions, getInsertionIndex?: (properties: string[]) => number): Edit[] { - let path = originalPath.slice(); - let errors: ParseError[] = []; - let root = parseTree(text, errors); + const path = originalPath.slice(); + const errors: ParseError[] = []; + const root = parseTree(text, errors); let parent: Node | undefined = undefined; let lastSegment: Segment | undefined = undefined; @@ -39,24 +40,24 @@ export function setProperty(text: string, originalPath: JSONPath, value: any, fo } return withFormatting(text, { offset: root ? root.offset : 0, length: root ? root.length : 0, content: JSON.stringify(value) }, formattingOptions); } else if (parent.type === 'object' && typeof lastSegment === 'string' && Array.isArray(parent.children)) { - let existing = findNodeAtLocation(parent, [lastSegment]); + const existing = findNodeAtLocation(parent, [lastSegment]); if (existing !== undefined) { if (value === undefined) { // delete if (!existing.parent) { throw new Error('Malformed AST'); } - let propertyIndex = parent.children.indexOf(existing.parent); + const propertyIndex = parent.children.indexOf(existing.parent); let removeBegin: number; let removeEnd = existing.parent.offset + existing.parent.length; if (propertyIndex > 0) { // remove the comma of the previous node - let previous = parent.children[propertyIndex - 1]; + const previous = parent.children[propertyIndex - 1]; removeBegin = previous.offset + previous.length; } else { removeBegin = parent.offset + 1; if (parent.children.length > 1) { // remove the comma of the next node - let next = parent.children[1]; + const next = parent.children[1]; removeEnd = next.offset; } } @@ -69,11 +70,11 @@ export function setProperty(text: string, originalPath: JSONPath, value: any, fo if (value === undefined) { // delete return []; // property does not exist, nothing to do } - let newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`; - let index = getInsertionIndex ? getInsertionIndex(parent.children.map(p => p.children![0].value)) : parent.children.length; + const newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`; + const index = getInsertionIndex ? getInsertionIndex(parent.children.map(p => p.children![0].value)) : parent.children.length; let edit: Edit; if (index > 0) { - let previous = parent.children[index - 1]; + const previous = parent.children[index - 1]; edit = { offset: previous.offset + previous.length, length: 0, content: ',' + newProperty }; } else if (parent.children.length === 0) { edit = { offset: parent.offset + 1, length: 0, content: newProperty }; @@ -83,32 +84,32 @@ export function setProperty(text: string, originalPath: JSONPath, value: any, fo return withFormatting(text, edit, formattingOptions); } } else if (parent.type === 'array' && typeof lastSegment === 'number' && Array.isArray(parent.children)) { - let insertIndex = lastSegment; + const insertIndex = lastSegment; if (insertIndex === -1) { // Insert - let newProperty = `${JSON.stringify(value)}`; + const newProperty = `${JSON.stringify(value)}`; let edit: Edit; if (parent.children.length === 0) { edit = { offset: parent.offset + 1, length: 0, content: newProperty }; } else { - let previous = parent.children[parent.children.length - 1]; + const previous = parent.children[parent.children.length - 1]; edit = { offset: previous.offset + previous.length, length: 0, content: ',' + newProperty }; } return withFormatting(text, edit, formattingOptions); } else { if (value === undefined && parent.children.length >= 0) { //Removal - let removalIndex = lastSegment; - let toRemove = parent.children[removalIndex]; + const removalIndex = lastSegment; + const toRemove = parent.children[removalIndex]; let edit: Edit; if (parent.children.length === 1) { // only item edit = { offset: parent.offset + 1, length: parent.length - 2, content: '' }; } else if (parent.children.length - 1 === removalIndex) { // last item - let previous = parent.children[removalIndex - 1]; - let offset = previous.offset + previous.length; - let parentEndOffset = parent.offset + parent.length; + const previous = parent.children[removalIndex - 1]; + const offset = previous.offset + previous.length; + const parentEndOffset = parent.offset + parent.length; edit = { offset, length: parentEndOffset - 2 - offset, content: '' }; } else { edit = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: '' }; @@ -139,18 +140,18 @@ function withFormatting(text: string, edit: Edit, formattingOptions: FormattingO } } - let edits = format(newText, { offset: begin, length: end - begin }, formattingOptions); + const edits = format(newText, { offset: begin, length: end - begin }, formattingOptions); // apply the formatting edits and track the begin and end offsets of the changes for (let i = edits.length - 1; i >= 0; i--) { - let edit = edits[i]; + const edit = edits[i]; newText = applyEdit(newText, edit); begin = Math.min(begin, edit.offset); end = Math.max(end, edit.offset + edit.length); end += edit.content.length - edit.length; } // create a single edit with all changes - let editLength = text.length - (newText.length - end) - begin; + const editLength = text.length - (newText.length - end) - begin; return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }]; } @@ -158,6 +159,27 @@ export function applyEdit(text: string, edit: Edit): string { return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length); } +export function applyEdits(text: string, edits: Edit[]): string { + let sortedEdits = mergeSort(edits, (a, b) => { + const diff = a.offset - b.offset; + if (diff === 0) { + return a.length - b.length; + } + return diff; + }); + let lastModifiedOffset = text.length; + for (let i = sortedEdits.length - 1; i >= 0; i--) { + let e = sortedEdits[i]; + if (e.offset + e.length <= lastModifiedOffset) { + text = applyEdit(text, e); + } else { + throw new Error('Overlapping edit'); + } + lastModifiedOffset = e.offset; + } + return text; +} + export function isWS(text: string, offset: number) { return '\r\n \t'.indexOf(text.charAt(offset)) !== -1; } \ No newline at end of file diff --git a/src/vs/base/common/jsonFormatter.ts b/src/vs/base/common/jsonFormatter.ts index df2a97ee5cd..a25c493c05d 100644 --- a/src/vs/base/common/jsonFormatter.ts +++ b/src/vs/base/common/jsonFormatter.ts @@ -80,7 +80,7 @@ export function format(documentText: string, range: Range | undefined, options: rangeStart = 0; rangeEnd = documentText.length; } - let eol = getEOL(options, documentText); + const eol = getEOL(options, documentText); let lineBreak = false; let indentLevel = 0; @@ -91,7 +91,7 @@ export function format(documentText: string, range: Range | undefined, options: indentValue = '\t'; } - let scanner = createScanner(formatText, false); + const scanner = createScanner(formatText, false); let hasError = false; function newLineAndIndent(): string { @@ -107,7 +107,7 @@ export function format(documentText: string, range: Range | undefined, options: hasError = token === SyntaxKind.Unknown || scanner.getTokenError() !== ScanError.None; return token; } - let editOperations: Edit[] = []; + const editOperations: Edit[] = []; function addEdit(text: string, startOffset: number, endOffset: number) { if (!hasError && startOffset < rangeEnd && endOffset > rangeStart && documentText.substring(startOffset, endOffset) !== text) { editOperations.push({ offset: startOffset, length: endOffset - startOffset, content: text }); @@ -117,8 +117,8 @@ export function format(documentText: string, range: Range | undefined, options: let firstToken = scanNext(); if (firstToken !== SyntaxKind.EOF) { - let firstTokenStart = scanner.getTokenOffset() + formatTextStart; - let initialIndent = repeat(indentValue, initialIndentLevel); + const firstTokenStart = scanner.getTokenOffset() + formatTextStart; + const initialIndent = repeat(indentValue, initialIndentLevel); addEdit(initialIndent, formatTextStart, firstTokenStart); } @@ -129,7 +129,7 @@ export function format(documentText: string, range: Range | undefined, options: let replaceContent = ''; while (!lineBreak && (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia)) { // comments on the same line: keep them on the same line, but ignore them otherwise - let commentTokenStart = scanner.getTokenOffset() + formatTextStart; + const commentTokenStart = scanner.getTokenOffset() + formatTextStart; addEdit(' ', firstTokenEnd, commentTokenStart); firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart; replaceContent = secondToken === SyntaxKind.LineCommentTrivia ? newLineAndIndent() : ''; @@ -195,7 +195,7 @@ export function format(documentText: string, range: Range | undefined, options: } } - let secondTokenStart = scanner.getTokenOffset() + formatTextStart; + const secondTokenStart = scanner.getTokenOffset() + formatTextStart; addEdit(replaceContent, firstTokenEnd, secondTokenStart); firstToken = secondToken; } @@ -213,9 +213,9 @@ function repeat(s: string, count: number): string { function computeIndentLevel(content: string, options: FormattingOptions): number { let i = 0; let nChars = 0; - let tabSize = options.tabSize || 4; + const tabSize = options.tabSize || 4; while (i < content.length) { - let ch = content.charAt(i); + const ch = content.charAt(i); if (ch === ' ') { nChars++; } else if (ch === '\t') { @@ -230,7 +230,7 @@ function computeIndentLevel(content: string, options: FormattingOptions): number function getEOL(options: FormattingOptions, text: string): string { for (let i = 0; i < text.length; i++) { - let ch = text.charAt(i); + const ch = text.charAt(i); if (ch === '\r') { if (i + 1 < text.length && text.charAt(i + 1) === '\n') { return '\r\n'; diff --git a/src/vs/base/common/keyCodes.ts b/src/vs/base/common/keyCodes.ts index c8e7b7c1579..ec08bea7e91 100644 --- a/src/vs/base/common/keyCodes.ts +++ b/src/vs/base/common/keyCodes.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { OperatingSystem } from 'vs/base/common/platform'; +import { illegalArgument } from 'vs/base/common/errors'; /** * Virtual Key Codes, the value does not hold any inherent meaning. @@ -406,7 +407,7 @@ export const enum KeyMod { } export function KeyChord(firstPart: number, secondPart: number): number { - let chordPart = ((secondPart & 0x0000FFFF) << 16) >>> 0; + const chordPart = ((secondPart & 0x0000FFFF) << 16) >>> 0; return (firstPart | chordPart) >>> 0; } @@ -417,12 +418,12 @@ export function createKeybinding(keybinding: number, OS: OperatingSystem): Keybi const firstPart = (keybinding & 0x0000FFFF) >>> 0; const chordPart = (keybinding & 0xFFFF0000) >>> 16; if (chordPart !== 0) { - return new ChordKeybinding( + return new ChordKeybinding([ createSimpleKeybinding(firstPart, OS), - createSimpleKeybinding(chordPart, OS), - ); + createSimpleKeybinding(chordPart, OS) + ]); } - return createSimpleKeybinding(firstPart, OS); + return new ChordKeybinding([createSimpleKeybinding(firstPart, OS)]); } export function createSimpleKeybinding(keybinding: number, OS: OperatingSystem): SimpleKeybinding { @@ -439,14 +440,7 @@ export function createSimpleKeybinding(keybinding: number, OS: OperatingSystem): return new SimpleKeybinding(ctrlKey, shiftKey, altKey, metaKey, keyCode); } -export const enum KeybindingType { - Simple = 1, - Chord = 2 -} - export class SimpleKeybinding { - public readonly type = KeybindingType.Simple; - public readonly ctrlKey: boolean; public readonly shiftKey: boolean; public readonly altKey: boolean; @@ -461,10 +455,7 @@ export class SimpleKeybinding { this.keyCode = keyCode; } - public equals(other: Keybinding): boolean { - if (other.type !== KeybindingType.Simple) { - return false; - } + public equals(other: SimpleKeybinding): boolean { return ( this.ctrlKey === other.ctrlKey && this.shiftKey === other.shiftKey @@ -475,10 +466,10 @@ export class SimpleKeybinding { } public getHashCode(): string { - let ctrl = this.ctrlKey ? '1' : '0'; - let shift = this.shiftKey ? '1' : '0'; - let alt = this.altKey ? '1' : '0'; - let meta = this.metaKey ? '1' : '0'; + const ctrl = this.ctrlKey ? '1' : '0'; + const shift = this.shiftKey ? '1' : '0'; + const alt = this.altKey ? '1' : '0'; + const meta = this.metaKey ? '1' : '0'; return `${ctrl}${shift}${alt}${meta}${this.keyCode}`; } @@ -492,6 +483,10 @@ export class SimpleKeybinding { ); } + public toChord(): ChordKeybinding { + return new ChordKeybinding([this]); + } + /** * Does this keybinding refer to the key code of a modifier and it also has the modifier flag? */ @@ -506,22 +501,43 @@ export class SimpleKeybinding { } export class ChordKeybinding { - public readonly type = KeybindingType.Chord; + public readonly parts: SimpleKeybinding[]; - public readonly firstPart: SimpleKeybinding; - public readonly chordPart: SimpleKeybinding; - - constructor(firstPart: SimpleKeybinding, chordPart: SimpleKeybinding) { - this.firstPart = firstPart; - this.chordPart = chordPart; + constructor(parts: SimpleKeybinding[]) { + if (parts.length === 0) { + throw illegalArgument(`parts`); + } + this.parts = parts; } public getHashCode(): string { - return `${this.firstPart.getHashCode()};${this.chordPart.getHashCode()}`; + let result = ''; + for (let i = 0, len = this.parts.length; i < len; i++) { + if (i !== 0) { + result += ';'; + } + result += this.parts[i].getHashCode(); + } + return result; + } + + public equals(other: ChordKeybinding | null): boolean { + if (other === null) { + return false; + } + if (this.parts.length !== other.parts.length) { + return false; + } + for (let i = 0; i < this.parts.length; i++) { + if (!this.parts[i].equals(other.parts[i])) { + return false; + } + } + return true; } } -export type Keybinding = SimpleKeybinding | ChordKeybinding; +export type Keybinding = ChordKeybinding; export class ResolvedKeybindingPart { readonly ctrlKey: boolean; @@ -574,12 +590,13 @@ export abstract class ResolvedKeybinding { public abstract isChord(): boolean; /** - * Returns the firstPart, chordPart that should be used for dispatching. + * Returns the parts that comprise of the keybinding. + * Simple keybindings return one element. */ - public abstract getDispatchParts(): [string | null, string | null]; + public abstract getParts(): ResolvedKeybindingPart[]; + /** - * Returns the firstPart, chordPart of the keybinding. - * For simple keybindings, the second element will be null. + * Returns the parts that should be used for dispatching. */ - public abstract getParts(): [ResolvedKeybindingPart, ResolvedKeybindingPart | null]; + public abstract getDispatchParts(): (string | null)[]; } diff --git a/src/vs/base/common/keybindingLabels.ts b/src/vs/base/common/keybindingLabels.ts index 30344e4d724..671816830bd 100644 --- a/src/vs/base/common/keybindingLabels.ts +++ b/src/vs/base/common/keybindingLabels.ts @@ -21,6 +21,10 @@ export interface Modifiers { readonly metaKey: boolean; } +export interface KeyLabelProvider { + (keybinding: T): string | null; +} + export class ModifierLabelProvider { public readonly modifierLabels: ModifierLabels[]; @@ -32,11 +36,22 @@ export class ModifierLabelProvider { this.modifierLabels[OperatingSystem.Linux] = linux; } - public toLabel(firstPartMod: Modifiers | null, firstPartKey: string | null, chordPartMod: Modifiers | null, chordPartKey: string | null, OS: OperatingSystem): string | null { - if (firstPartMod === null || firstPartKey === null) { + public toLabel(OS: OperatingSystem, parts: T[], keyLabelProvider: KeyLabelProvider): string | null { + if (parts.length === 0) { return null; } - return _asString(firstPartMod, firstPartKey, chordPartMod, chordPartKey, this.modifierLabels[OS]); + + const result: string[] = []; + for (let i = 0, len = parts.length; i < len; i++) { + const part = parts[i]; + const keyLabel = keyLabelProvider(part); + if (keyLabel === null) { + // this keybinding cannot be expressed... + return null; + } + result[i] = _simpleAsString(part, keyLabel, this.modifierLabels[OS]); + } + return result.join(' '); } } @@ -147,7 +162,7 @@ function _simpleAsString(modifiers: Modifiers, key: string, labels: ModifierLabe return ''; } - let result: string[] = []; + const result: string[] = []; // translate modifier keys: Ctrl-Shift-Alt-Meta if (modifiers.ctrlKey) { @@ -171,14 +186,3 @@ function _simpleAsString(modifiers: Modifiers, key: string, labels: ModifierLabe return result.join(labels.separator); } - -function _asString(firstPartMod: Modifiers, firstPartKey: string, chordPartMod: Modifiers | null, chordPartKey: string | null, labels: ModifierLabels): string { - let result = _simpleAsString(firstPartMod, firstPartKey, labels); - - if (chordPartMod !== null && chordPartKey !== null) { - result += ' '; - result += _simpleAsString(chordPartMod, chordPartKey, labels); - } - - return result; -} \ No newline at end of file diff --git a/src/vs/base/common/keybindingParser.ts b/src/vs/base/common/keybindingParser.ts index 1d2a0db8914..f7e120acc53 100644 --- a/src/vs/base/common/keybindingParser.ts +++ b/src/vs/base/common/keybindingParser.ts @@ -85,16 +85,14 @@ export class KeybindingParser { return null; } - let [firstPart, remains] = this.parseSimpleKeybinding(input); - let chordPart: SimpleKeybinding | null = null; - if (remains.length > 0) { - [chordPart] = this.parseSimpleKeybinding(remains); - } + const parts: SimpleKeybinding[] = []; + let part: SimpleKeybinding; - if (chordPart) { - return new ChordKeybinding(firstPart, chordPart); - } - return firstPart; + do { + [part, input] = this.parseSimpleKeybinding(input); + parts.push(part); + } while (input.length > 0); + return new ChordKeybinding(parts); } private static parseSimpleUserBinding(input: string): [SimpleKeybinding | ScanCodeBinding, string] { @@ -109,16 +107,18 @@ export class KeybindingParser { return [new SimpleKeybinding(mods.ctrl, mods.shift, mods.alt, mods.meta, keyCode), mods.remains]; } - static parseUserBinding(input: string): [SimpleKeybinding | ScanCodeBinding | null, SimpleKeybinding | ScanCodeBinding | null] { + static parseUserBinding(input: string): (SimpleKeybinding | ScanCodeBinding)[] { if (!input) { - return [null, null]; + return []; } - let [firstPart, remains] = this.parseSimpleUserBinding(input); - let chordPart: SimpleKeybinding | ScanCodeBinding | null = null; - if (remains.length > 0) { - [chordPart] = this.parseSimpleUserBinding(remains); + const parts: (SimpleKeybinding | ScanCodeBinding)[] = []; + let part: SimpleKeybinding | ScanCodeBinding; + + while (input.length > 0) { + [part, input] = this.parseSimpleUserBinding(input); + parts.push(part); } - return [firstPart, chordPart]; + return parts; } } \ No newline at end of file diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index c9e2a9b1733..39effeb6fdf 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -4,11 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { nativeSep, normalize, basename as pathsBasename, sep } from 'vs/base/common/paths'; -import { endsWith, ltrim, startsWithIgnoreCase, rtrim, startsWith } from 'vs/base/common/strings'; +import { sep, posix, normalize } from 'vs/base/common/path'; +import { endsWith, startsWithIgnoreCase, rtrim, startsWith } from 'vs/base/common/strings'; import { Schemas } from 'vs/base/common/network'; import { isLinux, isWindows, isMacintosh } from 'vs/base/common/platform'; -import { isEqual } from 'vs/base/common/resources'; +import { isEqual, basename, relativePath } from 'vs/base/common/resources'; +import { CharCode } from 'vs/base/common/charCode'; export interface IWorkspaceFolderProvider { getWorkspaceFolder(resource: URI): { uri: URI, name?: string } | null; @@ -36,14 +37,14 @@ export function getPathLabel(resource: URI | string, userHomeProvider?: IUserHom const hasMultipleRoots = rootProvider.getWorkspace().folders.length > 1; let pathLabel: string; - if (isEqual(baseResource.uri, resource, !isLinux)) { + if (isEqual(baseResource.uri, resource)) { pathLabel = ''; // no label if paths are identical } else { - pathLabel = normalize(ltrim(resource.path.substr(baseResource.uri.path.length), sep)!, true); + pathLabel = relativePath(baseResource.uri, resource)!; } if (hasMultipleRoots) { - const rootName = (baseResource && baseResource.name) ? baseResource.name : pathsBasename(baseResource.uri.fsPath); + const rootName = (baseResource && baseResource.name) ? baseResource.name : basename(baseResource.uri); pathLabel = pathLabel ? (rootName + ' • ' + pathLabel) : rootName; // always show root basename if there are multiple } @@ -58,11 +59,11 @@ export function getPathLabel(resource: URI | string, userHomeProvider?: IUserHom // convert c:\something => C:\something if (hasDriveLetter(resource.fsPath)) { - return normalize(normalizeDriveLetter(resource.fsPath), true); + return normalize(normalizeDriveLetter(resource.fsPath)); } // normalize and tildify (macOS, Linux only) - let res = normalize(resource.fsPath, true); + let res = normalize(resource.fsPath); if (!isWindows && userHomeProvider) { res = tildify(res, userHomeProvider.userHome); } @@ -81,7 +82,7 @@ export function getBaseLabel(resource: URI | string | undefined): string | undef resource = URI.file(resource); } - const base = pathsBasename(resource.path) || (resource.scheme === Schemas.file ? resource.fsPath : resource.path) /* can be empty string if '/' is passed in */; + const base = basename(resource) || (resource.scheme === Schemas.file ? resource.fsPath : resource.path) /* can be empty string if '/' is passed in */; // convert c: => C: if (hasDriveLetter(base)) { @@ -112,7 +113,7 @@ export function tildify(path: string, userHome: string): string { // Keep a normalized user home path as cache to prevent accumulated string creation let normalizedUserHome = normalizedUserHomeCached.original === userHome ? normalizedUserHomeCached.normalized : undefined; if (!normalizedUserHome) { - normalizedUserHome = `${rtrim(userHome, sep)}${sep}`; + normalizedUserHome = `${rtrim(userHome, posix.sep)}${posix.sep}`; normalizedUserHomeCached = { original: userHome, normalized: normalizedUserHome }; } @@ -169,7 +170,7 @@ export function shorten(paths: string[]): string[] { let path = paths[pathIndex]; if (path === '') { - shortenedPaths[pathIndex] = `.${nativeSep}`; + shortenedPaths[pathIndex] = `.${sep}`; continue; } @@ -185,20 +186,20 @@ export function shorten(paths: string[]): string[] { if (path.indexOf(unc) === 0) { prefix = path.substr(0, path.indexOf(unc) + unc.length); path = path.substr(path.indexOf(unc) + unc.length); - } else if (path.indexOf(nativeSep) === 0) { - prefix = path.substr(0, path.indexOf(nativeSep) + nativeSep.length); - path = path.substr(path.indexOf(nativeSep) + nativeSep.length); + } else if (path.indexOf(sep) === 0) { + prefix = path.substr(0, path.indexOf(sep) + sep.length); + path = path.substr(path.indexOf(sep) + sep.length); } else if (path.indexOf(home) === 0) { prefix = path.substr(0, path.indexOf(home) + home.length); path = path.substr(path.indexOf(home) + home.length); } // pick the first shortest subpath found - const segments: string[] = path.split(nativeSep); + const segments: string[] = path.split(sep); for (let subpathLength = 1; match && subpathLength <= segments.length; subpathLength++) { for (let start = segments.length - subpathLength; match && start >= 0; start--) { match = false; - let subpath = segments.slice(start, start + subpathLength).join(nativeSep); + let subpath = segments.slice(start, start + subpathLength).join(sep); // that is unique to any other path for (let otherPathIndex = 0; !match && otherPathIndex < paths.length; otherPathIndex++) { @@ -209,7 +210,7 @@ export function shorten(paths: string[]): string[] { // Adding separator as prefix for subpath, such that 'endsWith(src, trgt)' considers subpath as directory name instead of plain string. // prefix is not added when either subpath is root directory or path[otherPathIndex] does not have multiple directories. - const subpathWithSep: string = (start > 0 && paths[otherPathIndex].indexOf(nativeSep) > -1) ? nativeSep + subpath : subpath; + const subpathWithSep: string = (start > 0 && paths[otherPathIndex].indexOf(sep) > -1) ? sep + subpath : subpath; const isOtherPathEnding: boolean = endsWith(paths[otherPathIndex], subpathWithSep); match = !isSubpathEnding || isOtherPathEnding; @@ -226,11 +227,11 @@ export function shorten(paths: string[]): string[] { // extend subpath to include disk drive prefix start = 0; subpathLength++; - subpath = segments[0] + nativeSep + subpath; + subpath = segments[0] + sep + subpath; } if (start > 0) { - result = segments[0] + nativeSep; + result = segments[0] + sep; } result = prefix + result; @@ -238,14 +239,14 @@ export function shorten(paths: string[]): string[] { // add ellipsis at the beginning if neeeded if (start > 0) { - result = result + ellipsis + nativeSep; + result = result + ellipsis + sep; } result = result + subpath; // add ellipsis at the end if needed if (start + subpathLength < segments.length) { - result = result + nativeSep + ellipsis; + result = result + sep + ellipsis; } shortenedPaths[pathIndex] = result; @@ -282,7 +283,7 @@ interface ISegment { * @param value string to which templating is applied * @param values the values of the templates to use */ -export function template(template: string, values: { [key: string]: string | ISeparator } = Object.create(null)): string { +export function template(template: string, values: { [key: string]: string | ISeparator | null } = Object.create(null)): string { const segments: ISegment[] = []; let inVariable = false; @@ -355,10 +356,10 @@ export function template(template: string, values: { [key: string]: string | ISe */ export function mnemonicMenuLabel(label: string, forceDisableMnemonics?: boolean): string { if (isMacintosh || forceDisableMnemonics) { - return label.replace(/\(&&\w\)|&&/g, ''); + return label.replace(/\(&&\w\)|&&/g, '').replace(/&/g, isMacintosh ? '&' : '&&'); } - return label.replace(/&&/g, '&'); + return label.replace(/&&|&/g, m => m === '&' ? '&&' : '&'); } /** @@ -367,8 +368,8 @@ export function mnemonicMenuLabel(label: string, forceDisableMnemonics?: boolean * - Linux: Supported via _ character (replace && with _) * - macOS: Unsupported (replace && with empty string) */ -export function mnemonicButtonLabel(label: string): string { - if (isMacintosh) { +export function mnemonicButtonLabel(label: string, forceDisableMnemonics?: boolean): string { + if (isMacintosh || forceDisableMnemonics) { return label.replace(/\(&&\w\)|&&/g, ''); } @@ -382,3 +383,16 @@ export function mnemonicButtonLabel(label: string): string { export function unmnemonicLabel(label: string): string { return label.replace(/&/g, '&&'); } + +/** + * Splits a path in name and parent path, supporting both '/' and '\' + */ +export function splitName(fullPath: string): { name: string, parentPath: string } { + for (let i = fullPath.length - 1; i >= 1; i--) { + const code = fullPath.charCodeAt(i); + if (code === CharCode.Slash || code === CharCode.Backslash) { + return { parentPath: fullPath.substr(0, i), name: fullPath.substr(i + 1) }; + } + } + return { parentPath: '', name: fullPath }; +} diff --git a/src/vs/base/common/lifecycle.ts b/src/vs/base/common/lifecycle.ts index 512d2d1225f..6be438cee41 100644 --- a/src/vs/base/common/lifecycle.ts +++ b/src/vs/base/common/lifecycle.ts @@ -5,6 +5,45 @@ import { once } from 'vs/base/common/functional'; +/** + * Enables logging of potentially leaked disposables. + * + * A disposable is considered leaked if it is not disposed or not registered as the child of + * another disposable. This tracking is very simple an only works for classes that either + * extend Disposable or use a DisposableStore. This means there are a lot of false positives. + */ +const TRACK_DISPOSABLES = false; + +const __is_disposable_tracked__ = '__is_disposable_tracked__'; + +function markTracked(x: T): void { + if (!TRACK_DISPOSABLES) { + return; + } + + if (x && x !== Disposable.None) { + try { + (x as any)[__is_disposable_tracked__] = true; + } catch { + // noop + } + } +} + +function trackDisposable(x: T): T { + if (!TRACK_DISPOSABLES) { + return x; + } + + const stack = new Error('Potentially leaked disposable').stack!; + setTimeout(() => { + if (!(x as any)[__is_disposable_tracked__]) { + console.log(stack); + } + }, 3000); + return x; +} + export interface IDisposable { dispose(): void; } @@ -15,56 +54,193 @@ export function isDisposable(thing: E): thing is E & IDisposab } export function dispose(disposable: T): T; -export function dispose(...disposables: Array): T[]; -export function dispose(disposables: T[]): T[]; -export function dispose(first: T | T[], ...rest: T[]): T | T[] | undefined { - if (Array.isArray(first)) { - first.forEach(d => d && d.dispose()); +export function dispose(disposable: T | undefined): T | undefined; +export function dispose(disposables: Array): Array; +export function dispose(disposables: ReadonlyArray): ReadonlyArray; +export function dispose(disposables: T | T[] | undefined): T | T[] | undefined { + if (Array.isArray(disposables)) { + disposables.forEach(d => { + if (d) { + markTracked(d); + d.dispose(); + } + }); return []; - } else if (rest.length === 0) { - if (first) { - first.dispose(); - return first; - } - return undefined; + } else if (disposables) { + markTracked(disposables); + disposables.dispose(); + return disposables; } else { - dispose(first); - dispose(rest); - return []; + return undefined; } } -export function combinedDisposable(disposables: IDisposable[]): IDisposable { - return { dispose: () => dispose(disposables) }; +export function combinedDisposable(...disposables: IDisposable[]): IDisposable { + disposables.forEach(markTracked); + return trackDisposable({ dispose: () => dispose(disposables) }); } export function toDisposable(fn: () => void): IDisposable { - return { dispose() { fn(); } }; + const self = trackDisposable({ + dispose: () => { + markTracked(self); + fn(); + } + }); + return self; +} + +export class DisposableStore implements IDisposable { + private _toDispose = new Set(); + private _isDisposed = false; + + /** + * Dispose of all registered disposables and mark this object as disposed. + * + * Any future disposables added to this object will be disposed of on `add`. + */ + public dispose(): void { + if (this._isDisposed) { + return; + } + + markTracked(this); + this._isDisposed = true; + this.clear(); + } + + /** + * Dispose of all registered disposables but do not mark this object as disposed. + */ + public clear(): void { + this._toDispose.forEach(item => item.dispose()); + this._toDispose.clear(); + } + + public add(t: T): T { + if (!t) { + return t; + } + if ((t as any as DisposableStore) === this) { + throw new Error('Cannot register a disposable on itself!'); + } + + markTracked(t); + if (this._isDisposed) { + console.warn(new Error('Registering disposable on object that has already been disposed of').stack); + t.dispose(); + } else { + this._toDispose.add(t); + } + + return t; + } } export abstract class Disposable implements IDisposable { static None = Object.freeze({ dispose() { } }); - protected _toDispose: IDisposable[] = []; - protected get toDispose(): IDisposable[] { return this._toDispose; } + private readonly _store = new DisposableStore(); - private _lifecycle_disposable_isDisposed = false; + constructor() { + trackDisposable(this); + } public dispose(): void { - this._lifecycle_disposable_isDisposed = true; - this._toDispose = dispose(this._toDispose); + markTracked(this); + + this._store.dispose(); } protected _register(t: T): T { - if (this._lifecycle_disposable_isDisposed) { - console.warn('Registering disposable on object that has already been disposed.'); - t.dispose(); - } else { - this._toDispose.push(t); + if ((t as any as Disposable) === this) { + throw new Error('Cannot register a disposable on itself!'); + } + return this._store.add(t); + } +} + +/** + * Manages the lifecycle of a disposable value that may be changed. + * + * This ensures that when the the disposable value is changed, the previously held disposable is disposed of. You can + * also register a `MutableDisposable` on a `Disposable` to ensure it is automatically cleaned up. + */ +export class MutableDisposable implements IDisposable { + private _value?: T; + private _isDisposed = false; + + constructor() { + trackDisposable(this); + } + + get value(): T | undefined { + return this._isDisposed ? undefined : this._value; + } + + set value(value: T | undefined) { + if (this._isDisposed || value === this._value) { + return; } - return t; + if (this._value) { + this._value.dispose(); + } + if (value) { + markTracked(value); + } + this._value = value; + } + + clear() { + this.value = undefined; + } + + dispose(): void { + this._isDisposed = true; + markTracked(this); + if (this._value) { + this._value.dispose(); + } + this._value = undefined; + } +} + +/** + * Wrapper class that stores a disposable that is not currently "owned" by anyone. + * + * Example use cases: + * + * - Express that a function/method will take ownership of a disposable parameter. + * - Express that a function returns a disposable that the caller must explicitly take ownership of. + */ +export class UnownedDisposable extends Disposable { + private _hasBeenAcquired = false; + private _value?: T; + + public constructor(value: T) { + super(); + this._value = value; + } + + public acquire(): T { + if (this._hasBeenAcquired) { + throw new Error('This disposable has already been acquired'); + } + this._hasBeenAcquired = true; + const value = this._value!; + this._value = undefined; + return value; + } + + public dispose() { + super.dispose(); + if (!this._hasBeenAcquired) { + this._hasBeenAcquired = true; + this._value!.dispose(); + this._value = undefined; + } } } @@ -74,22 +250,21 @@ export interface IReference extends IDisposable { export abstract class ReferenceCollection { - private references: { [key: string]: { readonly object: T; counter: number; } } = Object.create(null); - - constructor() { } + private readonly references: Map = new Map(); acquire(key: string): IReference { - let reference = this.references[key]; + let reference = this.references.get(key); if (!reference) { - reference = this.references[key] = { counter: 0, object: this.createReferencedObject(key) }; + reference = { counter: 0, object: this.createReferencedObject(key) }; + this.references.set(key, reference); } const { object } = reference; const dispose = once(() => { - if (--reference.counter === 0) { - this.destroyReferencedObject(key, reference.object); - delete this.references[key]; + if (--reference!.counter === 0) { + this.destroyReferencedObject(key, reference!.object); + this.references.delete(key); } }); diff --git a/src/vs/base/common/linkedList.ts b/src/vs/base/common/linkedList.ts index 5673ae64808..54bb9253de6 100644 --- a/src/vs/base/common/linkedList.ts +++ b/src/vs/base/common/linkedList.ts @@ -6,19 +6,24 @@ import { Iterator, IteratorResult, FIN } from 'vs/base/common/iterator'; class Node { + + static readonly Undefined = new Node(undefined); + element: E; - next: Node | undefined; - prev: Node | undefined; + next: Node; + prev: Node; constructor(element: E) { this.element = element; + this.next = Node.Undefined; + this.prev = Node.Undefined; } } export class LinkedList { - private _first: Node | undefined; - private _last: Node | undefined; + private _first: Node = Node.Undefined; + private _last: Node = Node.Undefined; private _size: number = 0; get size(): number { @@ -26,12 +31,12 @@ export class LinkedList { } isEmpty(): boolean { - return !this._first; + return this._first === Node.Undefined; } clear(): void { - this._first = undefined; - this._last = undefined; + this._first = Node.Undefined; + this._last = Node.Undefined; this._size = 0; } @@ -45,7 +50,7 @@ export class LinkedList { private _insert(element: E, atTheEnd: boolean): () => void { const newNode = new Node(element); - if (!this._first) { + if (this._first === Node.Undefined) { this._first = newNode; this._last = newNode; @@ -64,12 +69,18 @@ export class LinkedList { oldFirst.prev = newNode; } this._size += 1; - return this._remove.bind(this, newNode); + + let didRemove = false; + return () => { + if (!didRemove) { + didRemove = true; + this._remove(newNode); + } + }; } - shift(): E | undefined { - if (!this._first) { + if (this._first === Node.Undefined) { return undefined; } else { const res = this._first.element; @@ -79,7 +90,7 @@ export class LinkedList { } pop(): E | undefined { - if (!this._last) { + if (this._last === Node.Undefined) { return undefined; } else { const res = this._last.element; @@ -89,38 +100,30 @@ export class LinkedList { } private _remove(node: Node): void { - let candidate: Node | undefined = this._first; - while (candidate instanceof Node) { - if (candidate !== node) { - candidate = candidate.next; - continue; - } - if (candidate.prev && candidate.next) { - // middle - let anchor = candidate.prev; - anchor.next = candidate.next; - candidate.next.prev = anchor; + if (node.prev !== Node.Undefined && node.next !== Node.Undefined) { + // middle + const anchor = node.prev; + anchor.next = node.next; + node.next.prev = anchor; - } else if (!candidate.prev && !candidate.next) { - // only node - this._first = undefined; - this._last = undefined; + } else if (node.prev === Node.Undefined && node.next === Node.Undefined) { + // only node + this._first = Node.Undefined; + this._last = Node.Undefined; - } else if (!candidate.next) { - // last - this._last = this._last!.prev!; - this._last.next = undefined; + } else if (node.next === Node.Undefined) { + // last + this._last = this._last!.prev!; + this._last.next = Node.Undefined; - } else if (!candidate.prev) { - // first - this._first = this._first!.next!; - this._first.prev = undefined; - } - - // done - this._size -= 1; - break; + } else if (node.prev === Node.Undefined) { + // first + this._first = this._first!.next!; + this._first.prev = Node.Undefined; } + + // done + this._size -= 1; } iterator(): Iterator { @@ -128,7 +131,7 @@ export class LinkedList { let node = this._first; return { next(): IteratorResult { - if (!node) { + if (node === Node.Undefined) { return FIN; } @@ -144,8 +147,8 @@ export class LinkedList { } toArray(): E[] { - let result: E[] = []; - for (let node = this._first; node instanceof Node; node = node.next) { + const result: E[] = []; + for (let node = this._first; node !== Node.Undefined; node = node.next) { result.push(node.element); } return result; diff --git a/src/vs/base/common/map.ts b/src/vs/base/common/map.ts index 05aed148d23..f1cce9af4ce 100644 --- a/src/vs/base/common/map.ts +++ b/src/vs/base/common/map.ts @@ -9,7 +9,7 @@ import { Iterator, IteratorResult, FIN } from './iterator'; export function values(set: Set): V[]; export function values(map: Map): V[]; -export function values(forEachable: { forEach(callback: (value: V, ...more: any[]) => any) }): V[] { +export function values(forEachable: { forEach(callback: (value: V, ...more: any[]) => any): void }): V[] { const result: V[] = []; forEachable.forEach(value => result.push(value)); return result; @@ -100,8 +100,8 @@ export class StringIterator implements IKeyIterator { } cmp(a: string): number { - let aCode = a.charCodeAt(0); - let thisCode = this._value.charCodeAt(this._pos); + const aCode = a.charCodeAt(0); + const thisCode = this._value.charCodeAt(this._pos); return aCode - thisCode; } @@ -112,9 +112,9 @@ export class StringIterator implements IKeyIterator { export class PathIterator implements IKeyIterator { - private _value: string; - private _from: number; - private _to: number; + private _value!: string; + private _from!: number; + private _to!: number; reset(key: string): this { this._value = key.replace(/\\$|\/$/, ''); @@ -149,11 +149,11 @@ export class PathIterator implements IKeyIterator { cmp(a: string): number { let aPos = 0; - let aLen = a.length; + const aLen = a.length; let thisPos = this._from; while (aPos < aLen && thisPos < this._to) { - let cmp = a.charCodeAt(aPos) - this._value.charCodeAt(thisPos); + const cmp = a.charCodeAt(aPos) - this._value.charCodeAt(thisPos); if (cmp !== 0) { return cmp; } @@ -176,9 +176,9 @@ export class PathIterator implements IKeyIterator { } class TernarySearchTreeNode { - segment: string; + segment!: string; value: E | undefined; - key: string; + key!: string; left: TernarySearchTreeNode | undefined; mid: TernarySearchTreeNode | undefined; right: TernarySearchTreeNode | undefined; @@ -210,7 +210,7 @@ export class TernarySearchTree { } set(key: string, element: E): E | undefined { - let iter = this._iter.reset(key); + const iter = this._iter.reset(key); let node: TernarySearchTreeNode; if (!this._root) { @@ -220,7 +220,7 @@ export class TernarySearchTree { node = this._root; while (true) { - let val = iter.cmp(node.segment); + const val = iter.cmp(node.segment); if (val > 0) { // left if (!node.left) { @@ -256,10 +256,10 @@ export class TernarySearchTree { } get(key: string): E | undefined { - let iter = this._iter.reset(key); + const iter = this._iter.reset(key); let node = this._root; while (node) { - let val = iter.cmp(node.segment); + const val = iter.cmp(node.segment); if (val > 0) { // left node = node.left; @@ -279,13 +279,13 @@ export class TernarySearchTree { delete(key: string): void { - let iter = this._iter.reset(key); - let stack: [-1 | 0 | 1, TernarySearchTreeNode][] = []; + const iter = this._iter.reset(key); + const stack: [-1 | 0 | 1, TernarySearchTreeNode][] = []; let node = this._root; // find and unset node while (node) { - let val = iter.cmp(node.segment); + const val = iter.cmp(node.segment); if (val > 0) { // left stack.push([1, node]); @@ -319,11 +319,11 @@ export class TernarySearchTree { } findSubstr(key: string): E | undefined { - let iter = this._iter.reset(key); + const iter = this._iter.reset(key); let node = this._root; let candidate: E | undefined = undefined; while (node) { - let val = iter.cmp(node.segment); + const val = iter.cmp(node.segment); if (val > 0) { // left node = node.left; @@ -343,10 +343,10 @@ export class TernarySearchTree { } findSuperstr(key: string): Iterator | undefined { - let iter = this._iter.reset(key); + const iter = this._iter.reset(key); let node = this._root; while (node) { - let val = iter.cmp(node.segment); + const val = iter.cmp(node.segment); if (val > 0) { // left node = node.left; @@ -373,7 +373,7 @@ export class TernarySearchTree { let res: { done: false; value: E; }; let idx: number; let data: E[]; - let next = (): IteratorResult => { + const next = (): IteratorResult => { if (!data) { // lazy till first invocation data = []; @@ -431,7 +431,7 @@ export class ResourceMap { this.map.set(this.toKey(resource), value); } - get(resource: URI): T { + get(resource: URI): T | undefined { return this.map.get(this.toKey(resource)); } @@ -610,7 +610,7 @@ export class LinkedMap { } values(): V[] { - let result: V[] = []; + const result: V[] = []; let current = this._head; while (current) { result.push(current.value); @@ -620,7 +620,7 @@ export class LinkedMap { } keys(): K[] { - let result: K[] = []; + const result: K[] = []; let current = this._head; while (current) { result.push(current.key); @@ -631,14 +631,14 @@ export class LinkedMap { /* VS Code / Monaco editor runs on es5 which has no Symbol.iterator keys(): IterableIterator { - let current = this._head; - let iterator: IterableIterator = { + const current = this._head; + const iterator: IterableIterator = { [Symbol.iterator]() { return iterator; }, next():IteratorResult { if (current) { - let result = { value: current.key, done: false }; + const result = { value: current.key, done: false }; current = current.next; return result; } else { @@ -650,14 +650,14 @@ export class LinkedMap { } values(): IterableIterator { - let current = this._head; - let iterator: IterableIterator = { + const current = this._head; + const iterator: IterableIterator = { [Symbol.iterator]() { return iterator; }, next():IteratorResult { if (current) { - let result = { value: current.value, done: false }; + const result = { value: current.value, done: false }; current = current.next; return result; } else { @@ -723,9 +723,21 @@ export class LinkedMap { this._tail = undefined; } else if (item === this._head) { + // This can only happend if size === 1 which is handle + // by the case above. + if (!item.next) { + throw new Error('Invalid list'); + } + item.next.previous = undefined; this._head = item.next; } else if (item === this._tail) { + // This can only happend if size === 1 which is handle + // by the case above. + if (!item.previous) { + throw new Error('Invalid list'); + } + item.previous.next = undefined; this._tail = item.previous; } else { @@ -737,6 +749,8 @@ export class LinkedMap { next.previous = previous; previous.next = next; } + item.next = undefined; + item.previous = undefined; } private touch(item: Item, touch: Touch): void { diff --git a/src/vs/base/common/marked/cgmanifest.json b/src/vs/base/common/marked/cgmanifest.json index b0c1ce8f3d5..f3477931d13 100644 --- a/src/vs/base/common/marked/cgmanifest.json +++ b/src/vs/base/common/marked/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "marked", "repositoryUrl": "https://github.com/markedjs/marked", - "commitHash": "78c977bc3a47f9e2fb146477d1ca3dad0cb134e6" + "commitHash": "529a8d4e185a8aa561e4d8d2891f8556b5717cd4" } }, "license": "MIT", - "version": "0.5.0" + "version": "0.6.2" } ], "version": 1 diff --git a/src/vs/base/common/marked/marked.js b/src/vs/base/common/marked/marked.js index bde18dff976..1288f459647 100644 --- a/src/vs/base/common/marked/marked.js +++ b/src/vs/base/common/marked/marked.js @@ -23,7 +23,7 @@ var block = { heading: /^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/, nptable: noop, blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, - list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, + list: /^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, html: '^ {0,3}(?:' // optional indentation + '<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)' // (1) + '|comment[^\\n]*(\\n+|$)' // (2) @@ -31,8 +31,8 @@ var block = { + '|\\n*' // (4) + '|\\n*' // (5) + '|)[\\s\\S]*?(?:\\n{2,}|$)' // (6) - + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag - + '|(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag + + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag + + '|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag + ')', def: /^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/, table: noop, @@ -48,8 +48,8 @@ block.def = edit(block.def) .replace('title', block._title) .getRegex(); -block.bullet = /(?:[*+-]|\d+\.)/; -block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; +block.bullet = /(?:[*+-]|\d{1,9}\.)/; +block.item = /^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/; block.item = edit(block.item, 'gm') .replace(/bull/g, block.bullet) .getRegex(); @@ -95,7 +95,7 @@ block.normal = merge({}, block); */ block.gfm = merge({}, block.normal, { - fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\n? *\1 *(?:\n+|$)/, + fences: /^ {0,3}(`{3,}|~{3,})([^`\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/, paragraph: /^/, heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ }); @@ -235,7 +235,7 @@ Lexer.prototype.token = function(src, top) { src = src.substring(cap[0].length); this.tokens.push({ type: 'code', - lang: cap[2], + lang: cap[2] ? cap[2].trim() : cap[2], text: cap[3] || '' }); continue; @@ -253,7 +253,7 @@ Lexer.prototype.token = function(src, top) { } // table no leading pipe (gfm) - if (top && (cap = this.rules.nptable.exec(src))) { + if (cap = this.rules.nptable.exec(src)) { item = { type: 'table', header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), @@ -346,7 +346,7 @@ Lexer.prototype.token = function(src, top) { // Remove the list item's bullet // so it is seen as the next token. space = item.length; - item = item.replace(/^ *([*+-]|\d+\.) +/, ''); + item = item.replace(/^ *([*+-]|\d+\.) */, ''); // Outdent whatever the // list item contains. Hacky. @@ -359,9 +359,10 @@ Lexer.prototype.token = function(src, top) { // Determine whether the next list item belongs here. // Backpedal if it does not belong in this list. - if (this.options.smartLists && i !== l - 1) { + if (i !== l - 1) { b = block.bullet.exec(cap[i + 1])[0]; - if (bull !== b && !(bull.length > 1 && b.length > 1)) { + if (bull.length > 1 ? b.length === 1 + : (b.length > 1 || (this.options.smartLists && b !== bull))) { src = cap.slice(i + 1).join('\n') + src; i = l - 1; } @@ -450,12 +451,12 @@ Lexer.prototype.token = function(src, top) { } // table (gfm) - if (top && (cap = this.rules.table.exec(src))) { + if (cap = this.rules.table.exec(src)) { item = { type: 'table', header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3] ? cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') : [] + cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [] }; if (item.header.length === item.align.length) { @@ -544,14 +545,19 @@ var inline = { link: /^!?\[(label)\]\(href(?:\s+(title))?\s*\)/, reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/, nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/, - strong: /^__([^\s])__(?!_)|^\*\*([^\s])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/, - em: /^_([^\s_])_(?!_)|^\*([^\s*"<\[])\*(?!\*)|^_([^\s][\s\S]*?[^\s_])_(?!_)|^_([^\s_][\s\S]*?[^\s])_(?!_)|^\*([^\s"<\[][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/, - code: /^(`+)\s*([\s\S]*?[^`]?)\s*\1(?!`)/, + strong: /^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/, + em: /^_([^\s_])_(?!_)|^\*([^\s*"<\[])\*(?!\*)|^_([^\s][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s"<\[][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/, + code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/, br: /^( {2,}|\\)\n(?!\s*$)/, del: noop, - text: /^[\s\S]+?(?=[\\?@\\[^_{|}~'; +inline.em = edit(inline.em).replace(/punctuation/g, inline._punctuation).getRegex(); + inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g; inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/; @@ -568,8 +574,8 @@ inline.tag = edit(inline.tag) .replace('attribute', inline._attribute) .getRegex(); -inline._label = /(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?/; -inline._href = /\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f\\]*\)|[^\s\x00-\x1f()\\])*?)/; +inline._label = /(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|`(?!`)|[^\[\]\\`])*?/; +inline._href = /\s*(<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*)/; inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/; inline.link = edit(inline.link) @@ -609,24 +615,23 @@ inline.pedantic = merge({}, inline.normal, { inline.gfm = merge({}, inline.normal, { escape: edit(inline.escape).replace('])', '~|])').getRegex(), - url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/) - .replace('email', inline._email) - .getRegex(), + _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/, + url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/, del: /^~+(?=\S)([\s\S]*?\S)~+/, - text: edit(inline.text) - .replace(']|', '~]|') - .replace('|', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|') - .getRegex() + text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\/i.test(cap[0])) { this.inLink = false; } + if (!this.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { + this.inRawBlock = true; + } else if (this.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { + this.inRawBlock = false; + } + src = src.substring(cap[0].length); out += this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]) - : cap[0] + : cap[0]; continue; } // link if (cap = this.rules.link.exec(src)) { + var lastParenIndex = findClosingBracket(cap[2], '()'); + if (lastParenIndex > -1) { + var linkLen = cap[0].length - (cap[2].length - lastParenIndex) - (cap[3] || '').length; + cap[2] = cap[2].substring(0, lastParenIndex); + cap[0] = cap[0].substring(0, linkLen).trim(); + cap[3] = ''; + } src = src.substring(cap[0].length); this.inLink = true; href = cap[2]; @@ -821,10 +803,51 @@ InlineLexer.prototype.output = function(src) { continue; } + // autolink + if (cap = this.rules.autolink.exec(src)) { + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = escape(this.mangle(cap[1])); + href = 'mailto:' + text; + } else { + text = escape(cap[1]); + href = text; + } + out += this.renderer.link(href, null, text); + continue; + } + + // url (gfm) + if (!this.inLink && (cap = this.rules.url.exec(src))) { + if (cap[2] === '@') { + text = escape(cap[0]); + href = 'mailto:' + text; + } else { + // do extended autolink path validation + do { + prevCapZero = cap[0]; + cap[0] = this.rules._backpedal.exec(cap[0])[0]; + } while (prevCapZero !== cap[0]); + text = escape(cap[0]); + if (cap[1] === 'www.') { + href = 'http://' + text; + } else { + href = text; + } + } + src = src.substring(cap[0].length); + out += this.renderer.link(href, null, text); + continue; + } + // text if (cap = this.rules.text.exec(src)) { src = src.substring(cap[0].length); - out += this.renderer.text(escape(this.smartypants(cap[0]))); + if (this.inRawBlock) { + out += this.renderer.text(cap[0]); + } else { + out += this.renderer.text(escape(this.smartypants(cap[0]))); + } continue; } @@ -838,7 +861,7 @@ InlineLexer.prototype.output = function(src) { InlineLexer.escapes = function(text) { return text ? text.replace(InlineLexer.rules._escapes, '$1') : text; -} +}; /** * Compile Link @@ -906,7 +929,8 @@ function Renderer(options) { this.options = options || marked.defaults; } -Renderer.prototype.code = function(code, lang, escaped) { +Renderer.prototype.code = function(code, infostring, escaped) { + var lang = (infostring || '').match(/\S*/)[0]; if (this.options.highlight) { var out = this.options.highlight(code, lang); if (out != null && out !== code) { @@ -937,13 +961,13 @@ Renderer.prototype.html = function(html) { return html; }; -Renderer.prototype.heading = function(text, level, raw) { +Renderer.prototype.heading = function(text, level, raw, slugger) { if (this.options.headerIds) { return '' + text + ' '; -} +}; Renderer.prototype.paragraph = function(text) { return '

    ' + text + '

    \n'; @@ -1025,24 +1049,8 @@ Renderer.prototype.del = function(text) { }; Renderer.prototype.link = function(href, title, text) { - if (this.options.sanitize) { - try { - var prot = decodeURIComponent(unescape(href)) - .replace(/[^\w:]/g, '') - .toLowerCase(); - } catch (e) { - return text; - } - if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { - return text; - } - } - if (this.options.baseUrl && !originIndependentUrl.test(href)) { - href = resolveUrl(this.options.baseUrl, href); - } - try { - href = encodeURI(href).replace(/%25/g, '%'); - } catch (e) { + href = cleanUrl(this.options.sanitize, this.options.baseUrl, href); + if (href === null) { return text; } var out = '?@[\]^`{|}~]/g, '') + .replace(/\s/g, '-'); + + if (this.seen.hasOwnProperty(slug)) { + var originalSlug = slug; + do { + this.seen[originalSlug]++; + slug = originalSlug + '-' + this.seen[originalSlug]; + } while (this.seen.hasOwnProperty(slug)); + } + this.seen[slug] = 0; + + return slug; +}; + /** * Helpers */ function escape(html, encode) { - return html - .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); + if (encode) { + if (escape.escapeTest.test(html)) { + return html.replace(escape.escapeReplace, function (ch) { return escape.replacements[ch]; }); + } + } else { + if (escape.escapeTestNoEncode.test(html)) { + return html.replace(escape.escapeReplaceNoEncode, function (ch) { return escape.replacements[ch]; }); + } + } + + return html; } +escape.escapeTest = /[&<>"']/; +escape.escapeReplace = /[&<>"']/g; +escape.replacements = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' +}; + +escape.escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/; +escape.escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g; + function unescape(html) { // explicitly match decimal, hex, and named HTML entities return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function(_, n) { @@ -1316,6 +1386,30 @@ function edit(regex, opt) { }; } +function cleanUrl(sanitize, base, href) { + if (sanitize) { + try { + var prot = decodeURIComponent(unescape(href)) + .replace(/[^\w:]/g, '') + .toLowerCase(); + } catch (e) { + return null; + } + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { + return null; + } + } + if (base && !originIndependentUrl.test(href)) { + href = resolveUrl(base, href); + } + try { + href = encodeURI(href).replace(/%25/g, '%'); + } catch (e) { + return null; + } + return href; +} + function resolveUrl(base, href) { if (!baseUrls[' ' + base]) { // we can ignore everything in base after the last slash of its path component, @@ -1418,6 +1512,26 @@ function rtrim(str, c, invert) { return str.substr(0, str.length - suffLen); } +function findClosingBracket(str, b) { + if (str.indexOf(b[1]) === -1) { + return -1; + } + var level = 0; + for (var i = 0; i < str.length; i++) { + if (str[i] === '\\') { + i++; + } else if (str[i] === b[0]) { + level++; + } else if (str[i] === b[1]) { + level--; + if (level < 0) { + return i; + } + } + } + return -1; +} + /** * Marked */ @@ -1446,7 +1560,7 @@ function marked(src, opt, callback) { i = 0; try { - tokens = Lexer.lex(src, opt) + tokens = Lexer.lex(src, opt); } catch (e) { return callback(e); } @@ -1545,7 +1659,7 @@ marked.getDefaults = function () { tables: true, xhtml: false }; -} +}; marked.defaults = marked.getDefaults(); @@ -1565,6 +1679,8 @@ marked.lexer = Lexer.lex; marked.InlineLexer = InlineLexer; marked.inlineLexer = InlineLexer.output; +marked.Slugger = Slugger; + marked.parse = marked; // BEGIN MONACOCHANGE @@ -1582,7 +1698,7 @@ __marked_exports = marked; // ESM-comment-begin define(function() { return __marked_exports; }); // ESM-comment-end - + // ESM-uncomment-begin // export var marked = __marked_exports; // export var Parser = __marked_exports.Parser; diff --git a/src/vs/base/common/mime.ts b/src/vs/base/common/mime.ts index dea84057f73..d9451a64def 100644 --- a/src/vs/base/common/mime.ts +++ b/src/vs/base/common/mime.ts @@ -3,10 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as paths from 'vs/base/common/paths'; -import * as strings from 'vs/base/common/strings'; -import * as arrays from 'vs/base/common/arrays'; +import { basename, posix, extname } from 'vs/base/common/path'; +import { endsWith, startsWithUTF8BOM, startsWith } from 'vs/base/common/strings'; +import { coalesce } from 'vs/base/common/arrays'; import { match } from 'vs/base/common/glob'; +import { URI } from 'vs/base/common/uri'; +import { Schemas } from 'vs/base/common/network'; +import { DataUri } from 'vs/base/common/resources'; export const MIME_TEXT = 'text/plain'; export const MIME_BINARY = 'application/octet-stream'; @@ -85,7 +88,7 @@ function toTextMimeAssociationItem(association: ITextMimeAssociation): ITextMime filenameLowercase: association.filename ? association.filename.toLowerCase() : undefined, extensionLowercase: association.extension ? association.extension.toLowerCase() : undefined, filepatternLowercase: association.filepattern ? association.filepattern.toLowerCase() : undefined, - filepatternOnPath: association.filepattern ? association.filepattern.indexOf(paths.sep) >= 0 : false + filepatternOnPath: association.filepattern ? association.filepattern.indexOf(posix.sep) >= 0 : false }; } @@ -106,13 +109,29 @@ export function clearTextMimes(onlyUserConfigured?: boolean): void { /** * Given a file, return the best matching mime type for it */ -export function guessMimeTypes(path: string | null, firstLine?: string): string[] { +export function guessMimeTypes(resource: URI | null, firstLine?: string): string[] { + let path: string | undefined; + if (resource) { + switch (resource.scheme) { + case Schemas.file: + path = resource.fsPath; + break; + case Schemas.data: + const metadata = DataUri.parseMetaData(resource); + path = metadata.get(DataUri.META_DATA_LABEL); + break; + default: + path = resource.path; + } + } + if (!path) { return [MIME_UNKNOWN]; } path = path.toLowerCase(); - const filename = paths.basename(path); + + const filename = basename(path); // 1.) User configured mappings have highest priority const configuredMime = guessMimeTypeByPath(path, filename, userRegisteredAssociations); @@ -166,7 +185,7 @@ function guessMimeTypeByPath(path: string, filename: string, associations: IText // Longest extension match if (association.extension) { if (!extensionMatch || association.extension.length > extensionMatch.extension!.length) { - if (strings.endsWith(filename, association.extensionLowercase!)) { + if (endsWith(filename, association.extensionLowercase!)) { extensionMatch = association; } } @@ -192,12 +211,16 @@ function guessMimeTypeByPath(path: string, filename: string, associations: IText } function guessMimeTypeByFirstline(firstLine: string): string | null { - if (strings.startsWithUTF8BOM(firstLine)) { + if (startsWithUTF8BOM(firstLine)) { firstLine = firstLine.substr(1); } if (firstLine.length > 0) { - for (const association of registeredAssociations) { + + // We want to prioritize associations based on the order they are registered so that the last registered + // association wins over all other. This is for https://github.com/Microsoft/vscode/issues/20074 + for (let i = registeredAssociations.length - 1; i >= 0; i--) { + const association = registeredAssociations[i]; if (!association.firstline) { continue; } @@ -230,12 +253,13 @@ export function isUnspecific(mime: string[] | string): boolean { * 2. Otherwise, if there are other extensions, suggest the first one. * 3. Otherwise, suggest the prefix. */ -export function suggestFilename(langId: string, prefix: string): string { +export function suggestFilename(mode: string | undefined, prefix: string): string { const extensions = registeredAssociations - .filter(assoc => !assoc.userConfigured && assoc.extension && assoc.id === langId) + .filter(assoc => !assoc.userConfigured && assoc.extension && assoc.id === mode) .map(assoc => assoc.extension); - const extensionsWithDotFirst = arrays.coalesce(extensions) - .filter(assoc => strings.startsWith(assoc, '.')); + + const extensionsWithDotFirst = coalesce(extensions) + .filter(assoc => startsWith(assoc, '.')); if (extensionsWithDotFirst.length > 0) { return prefix + extensionsWithDotFirst[0]; @@ -250,55 +274,57 @@ interface MapExtToMediaMimes { // Known media mimes that we can handle const mapExtToMediaMimes: MapExtToMediaMimes = { + '.aac': 'audio/x-aac', + '.avi': 'video/x-msvideo', '.bmp': 'image/bmp', + '.flv': 'video/x-flv', '.gif': 'image/gif', - '.jpg': 'image/jpg', - '.jpeg': 'image/jpg', - '.jpe': 'image/jpg', - '.png': 'image/png', - '.tiff': 'image/tiff', - '.tif': 'image/tiff', '.ico': 'image/x-icon', - '.tga': 'image/x-tga', - '.psd': 'image/vnd.adobe.photoshop', - '.webp': 'image/webp', + '.jpe': 'image/jpg', + '.jpeg': 'image/jpg', + '.jpg': 'image/jpg', + '.m1v': 'video/mpeg', + '.m2a': 'audio/mpeg', + '.m2v': 'video/mpeg', + '.m3a': 'audio/mpeg', '.mid': 'audio/midi', '.midi': 'audio/midi', - '.mp4a': 'audio/mp4', - '.mpga': 'audio/mpeg', + '.mk3d': 'video/x-matroska', + '.mks': 'video/x-matroska', + '.mkv': 'video/x-matroska', + '.mov': 'video/quicktime', + '.movie': 'video/x-sgi-movie', '.mp2': 'audio/mpeg', '.mp2a': 'audio/mpeg', '.mp3': 'audio/mpeg', - '.m2a': 'audio/mpeg', - '.m3a': 'audio/mpeg', - '.oga': 'audio/ogg', - '.ogg': 'audio/ogg', - '.spx': 'audio/ogg', - '.aac': 'audio/x-aac', - '.wav': 'audio/x-wav', - '.wma': 'audio/x-ms-wma', '.mp4': 'video/mp4', + '.mp4a': 'audio/mp4', '.mp4v': 'video/mp4', - '.mpg4': 'video/mp4', + '.mpe': 'video/mpeg', '.mpeg': 'video/mpeg', '.mpg': 'video/mpeg', - '.mpe': 'video/mpeg', - '.m1v': 'video/mpeg', - '.m2v': 'video/mpeg', + '.mpg4': 'video/mp4', + '.mpga': 'audio/mpeg', + '.oga': 'audio/ogg', + '.ogg': 'audio/ogg', '.ogv': 'video/ogg', + '.png': 'image/png', + '.psd': 'image/vnd.adobe.photoshop', '.qt': 'video/quicktime', - '.mov': 'video/quicktime', + '.spx': 'audio/ogg', + '.svg': 'image/svg+xml', + '.tga': 'image/x-tga', + '.tif': 'image/tiff', + '.tiff': 'image/tiff', + '.wav': 'audio/x-wav', '.webm': 'video/webm', - '.mkv': 'video/x-matroska', - '.mk3d': 'video/x-matroska', - '.mks': 'video/x-matroska', + '.webp': 'image/webp', + '.wma': 'audio/x-ms-wma', '.wmv': 'video/x-ms-wmv', - '.flv': 'video/x-flv', - '.avi': 'video/x-msvideo', - '.movie': 'video/x-sgi-movie' + '.woff': 'application/font-woff', }; export function getMediaMime(path: string): string | undefined { - const ext = paths.extname(path); + const ext = extname(path); return mapExtToMediaMimes[ext.toLowerCase()]; } diff --git a/src/vs/base/common/network.ts b/src/vs/base/common/network.ts index 1915b8fb6f3..46d2933a05e 100644 --- a/src/vs/base/common/network.ts +++ b/src/vs/base/common/network.ts @@ -42,4 +42,10 @@ export namespace Schemas { export const untitled: string = 'untitled'; export const data: string = 'data'; + + export const command: string = 'command'; + + export const vscodeRemote: string = 'vscode-remote'; + + export const userData: string = 'vscode-userdata'; } diff --git a/src/vs/base/common/objects.ts b/src/vs/base/common/objects.ts index ef5e8b59de4..1475bf4a550 100644 --- a/src/vs/base/common/objects.ts +++ b/src/vs/base/common/objects.ts @@ -14,11 +14,11 @@ export function deepClone(obj: T): T { return obj as any; } const result: any = Array.isArray(obj) ? [] : {}; - Object.keys(obj).forEach((key: string) => { - if (obj[key] && typeof obj[key] === 'object') { - result[key] = deepClone(obj[key]); + Object.keys(obj).forEach((key: string) => { + if ((obj)[key] && typeof (obj)[key] === 'object') { + result[key] = deepClone((obj)[key]); } else { - result[key] = obj[key]; + result[key] = (obj)[key]; } }); return result; @@ -30,11 +30,11 @@ export function deepFreeze(obj: T): T { } const stack: any[] = [obj]; while (stack.length > 0) { - let obj = stack.shift(); + const obj = stack.shift(); Object.freeze(obj); for (const key in obj) { if (_hasOwnProperty.call(obj, key)) { - let prop = obj[key]; + const prop = obj[key]; if (typeof prop === 'object' && !Object.isFrozen(prop)) { stack.push(prop); } @@ -175,34 +175,6 @@ export function equals(one: any, other: any): boolean { return true; } -function arrayToHash(array: string[]): { [name: string]: true } { - const result: any = {}; - for (const e of array) { - result[e] = true; - } - return result; -} - -/** - * Given an array of strings, returns a function which, given a string - * returns true or false whether the string is in that array. - */ -export function createKeywordMatcher(arr: string[], caseInsensitive: boolean = false): (str: string) => boolean { - if (caseInsensitive) { - arr = arr.map(function (x) { return x.toLowerCase(); }); - } - const hash = arrayToHash(arr); - if (caseInsensitive) { - return function (word) { - return hash[word.toLowerCase()] !== undefined && hash.hasOwnProperty(word.toLowerCase()); - }; - } else { - return function (word) { - return hash[word] !== undefined && hash.hasOwnProperty(word); - }; - } -} - /** * Calls JSON.Stringify with a replacer to break apart any circular references. * This prevents JSON.stringify from throwing the exception diff --git a/src/vs/base/common/parsers.ts b/src/vs/base/common/parsers.ts index da9010662fa..125b965f5e4 100644 --- a/src/vs/base/common/parsers.ts +++ b/src/vs/base/common/parsers.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as Types from 'vs/base/common/types'; - export const enum ValidationState { OK = 0, Info = 1, @@ -78,25 +76,4 @@ export abstract class Parser { public fatal(message: string): void { this._problemReporter.fatal(message); } - - protected static merge(destination: T, source: T, overwrite: boolean): void { - Object.keys(source).forEach((key: string) => { - let destValue = destination[key]; - let sourceValue = source[key]; - if (Types.isUndefined(sourceValue)) { - return; - } - if (Types.isUndefined(destValue)) { - destination[key] = sourceValue; - } else { - if (overwrite) { - if (Types.isObject(destValue) && Types.isObject(sourceValue)) { - this.merge(destValue, sourceValue, overwrite); - } else { - destination[key] = sourceValue; - } - } - } - }); - } } \ No newline at end of file diff --git a/src/vs/base/common/path.ts b/src/vs/base/common/path.ts new file mode 100644 index 00000000000..c8532347224 --- /dev/null +++ b/src/vs/base/common/path.ts @@ -0,0 +1,1683 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// NOTE: VSCode's copy of nodejs path library to be usable in common (non-node) namespace +// Copied from: https://github.com/nodejs/node/tree/43dd49c9782848c25e5b03448c8a0f923f13c158 + +/** + * Copyright Joyent, Inc. and other Node contributors. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import * as process from 'vs/base/common/process'; + +const CHAR_UPPERCASE_A = 65;/* A */ +const CHAR_LOWERCASE_A = 97; /* a */ +const CHAR_UPPERCASE_Z = 90; /* Z */ +const CHAR_LOWERCASE_Z = 122; /* z */ +const CHAR_DOT = 46; /* . */ +const CHAR_FORWARD_SLASH = 47; /* / */ +const CHAR_BACKWARD_SLASH = 92; /* \ */ +const CHAR_COLON = 58; /* : */ +const CHAR_QUESTION_MARK = 63; /* ? */ + +class ErrorInvalidArgType extends Error { + code: 'ERR_INVALID_ARG_TYPE'; + constructor(name: string, expected: string, actual: any) { + // determiner: 'must be' or 'must not be' + let determiner; + if (typeof expected === 'string' && expected.indexOf('not ') === 0) { + determiner = 'must not be'; + expected = expected.replace(/^not /, ''); + } else { + determiner = 'must be'; + } + + const type = name.indexOf('.') !== -1 ? 'property' : 'argument'; + let msg = `The "${name}" ${type} ${determiner} of type ${expected}`; + + msg += `. Received type ${typeof actual}`; + super(msg); + } +} + +function validateString(value: string, name: string) { + if (typeof value !== 'string') { + throw new ErrorInvalidArgType(name, 'string', value); + } +} + +function isPathSeparator(code: number) { + return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; +} + +function isPosixPathSeparator(code: number) { + return code === CHAR_FORWARD_SLASH; +} + +function isWindowsDeviceRoot(code: number) { + return code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z || + code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z; +} + +// Resolves . and .. elements in a path with directory names +function normalizeString(path: string, allowAboveRoot: boolean, separator: string, isPathSeparator: (code?: number) => boolean) { + let res = ''; + let lastSegmentLength = 0; + let lastSlash = -1; + let dots = 0; + let code; + for (let i = 0; i <= path.length; ++i) { + if (i < path.length) { + code = path.charCodeAt(i); + } + else if (isPathSeparator(code)) { + break; + } + else { + code = CHAR_FORWARD_SLASH; + } + + if (isPathSeparator(code)) { + if (lastSlash === i - 1 || dots === 1) { + // NOOP + } else if (lastSlash !== i - 1 && dots === 2) { + if (res.length < 2 || lastSegmentLength !== 2 || + res.charCodeAt(res.length - 1) !== CHAR_DOT || + res.charCodeAt(res.length - 2) !== CHAR_DOT) { + if (res.length > 2) { + const lastSlashIndex = res.lastIndexOf(separator); + if (lastSlashIndex === -1) { + res = ''; + lastSegmentLength = 0; + } else { + res = res.slice(0, lastSlashIndex); + lastSegmentLength = res.length - 1 - res.lastIndexOf(separator); + } + lastSlash = i; + dots = 0; + continue; + } else if (res.length === 2 || res.length === 1) { + res = ''; + lastSegmentLength = 0; + lastSlash = i; + dots = 0; + continue; + } + } + if (allowAboveRoot) { + if (res.length > 0) { + res += `${separator}..`; + } + else { + res = '..'; + } + lastSegmentLength = 2; + } + } else { + if (res.length > 0) { + res += separator + path.slice(lastSlash + 1, i); + } + else { + res = path.slice(lastSlash + 1, i); + } + lastSegmentLength = i - lastSlash - 1; + } + lastSlash = i; + dots = 0; + } else if (code === CHAR_DOT && dots !== -1) { + ++dots; + } else { + dots = -1; + } + } + return res; +} + +function _format(sep: string, pathObject: ParsedPath) { + const dir = pathObject.dir || pathObject.root; + const base = pathObject.base || + ((pathObject.name || '') + (pathObject.ext || '')); + if (!dir) { + return base; + } + if (dir === pathObject.root) { + return dir + base; + } + return dir + sep + base; +} + +interface ParsedPath { + root: string; + dir: string; + base: string; + ext: string; + name: string; +} + +interface IPath { + normalize(path: string): string; + isAbsolute(path: string): boolean; + join(...paths: string[]): string; + resolve(...pathSegments: string[]): string; + relative(from: string, to: string): string; + dirname(path: string): string; + basename(path: string, ext?: string): string; + extname(path: string): string; + format(pathObject: ParsedPath): string; + parse(path: string): ParsedPath; + toNamespacedPath(path: string): string; + sep: '\\' | '/'; + delimiter: string; + win32: IPath | null; + posix: IPath | null; +} + +export const win32: IPath = { + // path.resolve([from ...], to) + resolve(...pathSegments: string[]): string { + let resolvedDevice = ''; + let resolvedTail = ''; + let resolvedAbsolute = false; + + for (let i = pathSegments.length - 1; i >= -1; i--) { + let path; + if (i >= 0) { + path = pathSegments[i]; + } else if (!resolvedDevice) { + path = process.cwd(); + } else { + // Windows has the concept of drive-specific current working + // directories. If we've resolved a drive letter but not yet an + // absolute path, get cwd for that drive, or the process cwd if + // the drive cwd is not available. We're sure the device is not + // a UNC path at this points, because UNC paths are always absolute. + path = (process.env as any)['=' + resolvedDevice] || process.cwd(); + + // Verify that a cwd was found and that it actually points + // to our drive. If not, default to the drive's root. + if (path === undefined || + path.slice(0, 3).toLowerCase() !== + resolvedDevice.toLowerCase() + '\\') { + path = resolvedDevice + '\\'; + } + } + + validateString(path, 'path'); + + // Skip empty entries + if (path.length === 0) { + continue; + } + + const len = path.length; + let rootEnd = 0; + let device = ''; + let isAbsolute = false; + const code = path.charCodeAt(0); + + // Try to match a root + if (len > 1) { + if (isPathSeparator(code)) { + // Possible UNC root + + // If we started with a separator, we know we at least have an + // absolute path of some kind (UNC or otherwise) + isAbsolute = true; + + if (isPathSeparator(path.charCodeAt(1))) { + // Matched double path separator at beginning + let j = 2; + let last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + const firstPart = path.slice(last, j); + // Matched! + last = j; + // Match 1 or more path separators + for (; j < len; ++j) { + if (!isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j === len) { + // We matched a UNC root only + + device = '\\\\' + firstPart + '\\' + path.slice(last); + rootEnd = j; + } else if (j !== last) { + // We matched a UNC root with leftovers + + device = '\\\\' + firstPart + '\\' + path.slice(last, j); + rootEnd = j; + } + } + } + } else { + rootEnd = 1; + } + } else if (isWindowsDeviceRoot(code)) { + // Possible device root + + if (path.charCodeAt(1) === CHAR_COLON) { + device = path.slice(0, 2); + rootEnd = 2; + if (len > 2) { + if (isPathSeparator(path.charCodeAt(2))) { + // Treat separator following drive name as an absolute path + // indicator + isAbsolute = true; + rootEnd = 3; + } + } + } + } + } else if (isPathSeparator(code)) { + // `path` contains just a path separator + rootEnd = 1; + isAbsolute = true; + } + + if (device.length > 0 && + resolvedDevice.length > 0 && + device.toLowerCase() !== resolvedDevice.toLowerCase()) { + // This path points to another device so it is not applicable + continue; + } + + if (resolvedDevice.length === 0 && device.length > 0) { + resolvedDevice = device; + } + if (!resolvedAbsolute) { + resolvedTail = path.slice(rootEnd) + '\\' + resolvedTail; + resolvedAbsolute = isAbsolute; + } + + if (resolvedDevice.length > 0 && resolvedAbsolute) { + break; + } + } + + // At this point the path should be resolved to a full absolute path, + // but handle relative paths to be safe (might happen when process.cwd() + // fails) + + // Normalize the tail path + resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\', + isPathSeparator); + + return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) || + '.'; + }, + + normalize(path: string): string { + validateString(path, 'path'); + const len = path.length; + if (len === 0) { + return '.'; + } + let rootEnd = 0; + let device; + let isAbsolute = false; + const code = path.charCodeAt(0); + + // Try to match a root + if (len > 1) { + if (isPathSeparator(code)) { + // Possible UNC root + + // If we started with a separator, we know we at least have an absolute + // path of some kind (UNC or otherwise) + isAbsolute = true; + + if (isPathSeparator(path.charCodeAt(1))) { + // Matched double path separator at beginning + let j = 2; + let last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + const firstPart = path.slice(last, j); + // Matched! + last = j; + // Match 1 or more path separators + for (; j < len; ++j) { + if (!isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j === len) { + // We matched a UNC root only + // Return the normalized version of the UNC root since there + // is nothing left to process + + return '\\\\' + firstPart + '\\' + path.slice(last) + '\\'; + } else if (j !== last) { + // We matched a UNC root with leftovers + + device = '\\\\' + firstPart + '\\' + path.slice(last, j); + rootEnd = j; + } + } + } + } else { + rootEnd = 1; + } + } else if (isWindowsDeviceRoot(code)) { + // Possible device root + + if (path.charCodeAt(1) === CHAR_COLON) { + device = path.slice(0, 2); + rootEnd = 2; + if (len > 2) { + if (isPathSeparator(path.charCodeAt(2))) { + // Treat separator following drive name as an absolute path + // indicator + isAbsolute = true; + rootEnd = 3; + } + } + } + } + } else if (isPathSeparator(code)) { + // `path` contains just a path separator, exit early to avoid unnecessary + // work + return '\\'; + } + + let tail; + if (rootEnd < len) { + tail = normalizeString(path.slice(rootEnd), !isAbsolute, '\\', + isPathSeparator); + } else { + tail = ''; + } + if (tail.length === 0 && !isAbsolute) { + tail = '.'; + } + if (tail.length > 0 && isPathSeparator(path.charCodeAt(len - 1))) { + tail += '\\'; + } + if (device === undefined) { + if (isAbsolute) { + if (tail.length > 0) { + return '\\' + tail; + } + else { + return '\\'; + } + } else if (tail.length > 0) { + return tail; + } else { + return ''; + } + } else if (isAbsolute) { + if (tail.length > 0) { + return device + '\\' + tail; + } + else { + return device + '\\'; + } + } else if (tail.length > 0) { + return device + tail; + } else { + return device; + } + }, + + isAbsolute(path: string): boolean { + validateString(path, 'path'); + const len = path.length; + if (len === 0) { + return false; + } + + const code = path.charCodeAt(0); + if (isPathSeparator(code)) { + return true; + } else if (isWindowsDeviceRoot(code)) { + // Possible device root + + if (len > 2 && path.charCodeAt(1) === CHAR_COLON) { + if (isPathSeparator(path.charCodeAt(2))) { + return true; + } + } + } + return false; + }, + + join(...paths: string[]): string { + if (paths.length === 0) { + return '.'; + } + + let joined; + let firstPart: string | undefined; + for (let i = 0; i < paths.length; ++i) { + const arg = paths[i]; + validateString(arg, 'path'); + if (arg.length > 0) { + if (joined === undefined) { + joined = firstPart = arg; + } + else { + joined += '\\' + arg; + } + } + } + + if (joined === undefined) { + return '.'; + } + + // Make sure that the joined path doesn't start with two slashes, because + // normalize() will mistake it for an UNC path then. + // + // This step is skipped when it is very clear that the user actually + // intended to point at an UNC path. This is assumed when the first + // non-empty string arguments starts with exactly two slashes followed by + // at least one more non-slash character. + // + // Note that for normalize() to treat a path as an UNC path it needs to + // have at least 2 components, so we don't filter for that here. + // This means that the user can use join to construct UNC paths from + // a server name and a share name; for example: + // path.join('//server', 'share') -> '\\\\server\\share\\') + let needsReplace = true; + let slashCount = 0; + if (typeof firstPart === 'string' && isPathSeparator(firstPart.charCodeAt(0))) { + ++slashCount; + const firstLen = firstPart.length; + if (firstLen > 1) { + if (isPathSeparator(firstPart.charCodeAt(1))) { + ++slashCount; + if (firstLen > 2) { + if (isPathSeparator(firstPart.charCodeAt(2))) { + ++slashCount; + } + else { + // We matched a UNC path in the first part + needsReplace = false; + } + } + } + } + } + if (needsReplace) { + // Find any more consecutive slashes we need to replace + for (; slashCount < joined.length; ++slashCount) { + if (!isPathSeparator(joined.charCodeAt(slashCount))) { + break; + } + } + + // Replace the slashes if needed + if (slashCount >= 2) { + joined = '\\' + joined.slice(slashCount); + } + } + + return win32.normalize(joined); + }, + + + // It will solve the relative path from `from` to `to`, for instance: + // from = 'C:\\orandea\\test\\aaa' + // to = 'C:\\orandea\\impl\\bbb' + // The output of the function should be: '..\\..\\impl\\bbb' + relative(from: string, to: string): string { + validateString(from, 'from'); + validateString(to, 'to'); + + if (from === to) { + return ''; + } + + const fromOrig = win32.resolve(from); + const toOrig = win32.resolve(to); + + if (fromOrig === toOrig) { + return ''; + } + + from = fromOrig.toLowerCase(); + to = toOrig.toLowerCase(); + + if (from === to) { + return ''; + } + + // Trim any leading backslashes + let fromStart = 0; + for (; fromStart < from.length; ++fromStart) { + if (from.charCodeAt(fromStart) !== CHAR_BACKWARD_SLASH) { + break; + } + } + // Trim trailing backslashes (applicable to UNC paths only) + let fromEnd = from.length; + for (; fromEnd - 1 > fromStart; --fromEnd) { + if (from.charCodeAt(fromEnd - 1) !== CHAR_BACKWARD_SLASH) { + break; + } + } + const fromLen = (fromEnd - fromStart); + + // Trim any leading backslashes + let toStart = 0; + for (; toStart < to.length; ++toStart) { + if (to.charCodeAt(toStart) !== CHAR_BACKWARD_SLASH) { + break; + } + } + // Trim trailing backslashes (applicable to UNC paths only) + let toEnd = to.length; + for (; toEnd - 1 > toStart; --toEnd) { + if (to.charCodeAt(toEnd - 1) !== CHAR_BACKWARD_SLASH) { + break; + } + } + const toLen = (toEnd - toStart); + + // Compare paths to find the longest common path from root + const length = (fromLen < toLen ? fromLen : toLen); + let lastCommonSep = -1; + let i = 0; + for (; i <= length; ++i) { + if (i === length) { + if (toLen > length) { + if (to.charCodeAt(toStart + i) === CHAR_BACKWARD_SLASH) { + // We get here if `from` is the exact base path for `to`. + // For example: from='C:\\foo\\bar'; to='C:\\foo\\bar\\baz' + return toOrig.slice(toStart + i + 1); + } else if (i === 2) { + // We get here if `from` is the device root. + // For example: from='C:\\'; to='C:\\foo' + return toOrig.slice(toStart + i); + } + } + if (fromLen > length) { + if (from.charCodeAt(fromStart + i) === CHAR_BACKWARD_SLASH) { + // We get here if `to` is the exact base path for `from`. + // For example: from='C:\\foo\\bar'; to='C:\\foo' + lastCommonSep = i; + } else if (i === 2) { + // We get here if `to` is the device root. + // For example: from='C:\\foo\\bar'; to='C:\\' + lastCommonSep = 3; + } + } + break; + } + const fromCode = from.charCodeAt(fromStart + i); + const toCode = to.charCodeAt(toStart + i); + if (fromCode !== toCode) { + break; + } + else if (fromCode === CHAR_BACKWARD_SLASH) { + lastCommonSep = i; + } + } + + // We found a mismatch before the first common path separator was seen, so + // return the original `to`. + if (i !== length && lastCommonSep === -1) { + return toOrig; + } + + let out = ''; + if (lastCommonSep === -1) { + lastCommonSep = 0; + } + // Generate the relative path based on the path difference between `to` and + // `from` + for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { + if (i === fromEnd || from.charCodeAt(i) === CHAR_BACKWARD_SLASH) { + if (out.length === 0) { + out += '..'; + } + else { + out += '\\..'; + } + } + } + + // Lastly, append the rest of the destination (`to`) path that comes after + // the common path parts + if (out.length > 0) { + return out + toOrig.slice(toStart + lastCommonSep, toEnd); + } + else { + toStart += lastCommonSep; + if (toOrig.charCodeAt(toStart) === CHAR_BACKWARD_SLASH) { + ++toStart; + } + return toOrig.slice(toStart, toEnd); + } + }, + + toNamespacedPath(path: string): string { + // Note: this will *probably* throw somewhere. + if (typeof path !== 'string') { + return path; + } + + if (path.length === 0) { + return ''; + } + + const resolvedPath = win32.resolve(path); + + if (resolvedPath.length >= 3) { + if (resolvedPath.charCodeAt(0) === CHAR_BACKWARD_SLASH) { + // Possible UNC root + + if (resolvedPath.charCodeAt(1) === CHAR_BACKWARD_SLASH) { + const code = resolvedPath.charCodeAt(2); + if (code !== CHAR_QUESTION_MARK && code !== CHAR_DOT) { + // Matched non-long UNC root, convert the path to a long UNC path + return '\\\\?\\UNC\\' + resolvedPath.slice(2); + } + } + } else if (isWindowsDeviceRoot(resolvedPath.charCodeAt(0))) { + // Possible device root + + if (resolvedPath.charCodeAt(1) === CHAR_COLON && + resolvedPath.charCodeAt(2) === CHAR_BACKWARD_SLASH) { + // Matched device root, convert the path to a long UNC path + return '\\\\?\\' + resolvedPath; + } + } + } + + return path; + }, + + dirname(path: string): string { + validateString(path, 'path'); + const len = path.length; + if (len === 0) { + return '.'; + } + let rootEnd = -1; + let end = -1; + let matchedSlash = true; + let offset = 0; + const code = path.charCodeAt(0); + + // Try to match a root + if (len > 1) { + if (isPathSeparator(code)) { + // Possible UNC root + + rootEnd = offset = 1; + + if (isPathSeparator(path.charCodeAt(1))) { + // Matched double path separator at beginning + let j = 2; + let last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more path separators + for (; j < len; ++j) { + if (!isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j === len) { + // We matched a UNC root only + return path; + } + if (j !== last) { + // We matched a UNC root with leftovers + + // Offset by 1 to include the separator after the UNC root to + // treat it as a "normal root" on top of a (UNC) root + rootEnd = offset = j + 1; + } + } + } + } + } else if (isWindowsDeviceRoot(code)) { + // Possible device root + + if (path.charCodeAt(1) === CHAR_COLON) { + rootEnd = offset = 2; + if (len > 2) { + if (isPathSeparator(path.charCodeAt(2))) { + rootEnd = offset = 3; + } + } + } + } + } else if (isPathSeparator(code)) { + // `path` contains just a path separator, exit early to avoid + // unnecessary work + return path; + } + + for (let i = len - 1; i >= offset; --i) { + if (isPathSeparator(path.charCodeAt(i))) { + if (!matchedSlash) { + end = i; + break; + } + } else { + // We saw the first non-path separator + matchedSlash = false; + } + } + + if (end === -1) { + if (rootEnd === -1) { + return '.'; + } + else { + end = rootEnd; + } + } + return path.slice(0, end); + }, + + basename(path: string, ext?: string): string { + if (ext !== undefined) { + validateString(ext, 'ext'); + } + validateString(path, 'path'); + let start = 0; + let end = -1; + let matchedSlash = true; + let i; + + // Check for a drive letter prefix so as not to mistake the following + // path separator as an extra separator at the end of the path that can be + // disregarded + if (path.length >= 2) { + const drive = path.charCodeAt(0); + if (isWindowsDeviceRoot(drive)) { + if (path.charCodeAt(1) === CHAR_COLON) { + start = 2; + } + } + } + + if (ext !== undefined && ext.length > 0 && ext.length <= path.length) { + if (ext.length === path.length && ext === path) { + return ''; + } + let extIdx = ext.length - 1; + let firstNonSlashEnd = -1; + for (i = path.length - 1; i >= start; --i) { + const code = path.charCodeAt(i); + if (isPathSeparator(code)) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; + } + } else { + if (firstNonSlashEnd === -1) { + // We saw the first non-path separator, remember this index in case + // we need it if the extension ends up not matching + matchedSlash = false; + firstNonSlashEnd = i + 1; + } + if (extIdx >= 0) { + // Try to match the explicit extension + if (code === ext.charCodeAt(extIdx)) { + if (--extIdx === -1) { + // We matched the extension, so mark this as the end of our path + // component + end = i; + } + } else { + // Extension does not match, so our result is the entire path + // component + extIdx = -1; + end = firstNonSlashEnd; + } + } + } + } + + if (start === end) { + end = firstNonSlashEnd; + } + else if (end === -1) { + end = path.length; + } + return path.slice(start, end); + } else { + for (i = path.length - 1; i >= start; --i) { + if (isPathSeparator(path.charCodeAt(i))) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; + } + } else if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // path component + matchedSlash = false; + end = i + 1; + } + } + + if (end === -1) { + return ''; + } + return path.slice(start, end); + } + }, + + extname(path: string): string { + validateString(path, 'path'); + let start = 0; + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + + // Check for a drive letter prefix so as not to mistake the following + // path separator as an extra separator at the end of the path that can be + // disregarded + + if (path.length >= 2 && + path.charCodeAt(1) === CHAR_COLON && + isWindowsDeviceRoot(path.charCodeAt(0))) { + start = startPart = 2; + } + + for (let i = path.length - 1; i >= start; --i) { + const code = path.charCodeAt(i); + if (isPathSeparator(code)) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) { + startDot = i; + } + else if (preDotState !== 1) { + preDotState = 1; + } + } else if (startDot !== -1) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } + + if (startDot === -1 || + end === -1 || + // We saw a non-dot character immediately before the dot + preDotState === 0 || + // The (right-most) trimmed path component is exactly '..' + (preDotState === 1 && + startDot === end - 1 && + startDot === startPart + 1)) { + return ''; + } + return path.slice(startDot, end); + }, + + format(pathObject): string { + if (pathObject === null || typeof pathObject !== 'object') { + throw new ErrorInvalidArgType('pathObject', 'Object', pathObject); + } + + return _format('\\', pathObject); + }, + + + parse(path) { + validateString(path, 'path'); + + const ret = { root: '', dir: '', base: '', ext: '', name: '' }; + if (path.length === 0) { + return ret; + } + + const len = path.length; + let rootEnd = 0; + let code = path.charCodeAt(0); + + // Try to match a root + if (len > 1) { + if (isPathSeparator(code)) { + // Possible UNC root + + rootEnd = 1; + if (isPathSeparator(path.charCodeAt(1))) { + // Matched double path separator at beginning + let j = 2; + let last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more path separators + for (; j < len; ++j) { + if (!isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j === len) { + // We matched a UNC root only + + rootEnd = j; + } else if (j !== last) { + // We matched a UNC root with leftovers + + rootEnd = j + 1; + } + } + } + } + } else if (isWindowsDeviceRoot(code)) { + // Possible device root + + if (path.charCodeAt(1) === CHAR_COLON) { + rootEnd = 2; + if (len > 2) { + if (isPathSeparator(path.charCodeAt(2))) { + if (len === 3) { + // `path` contains just a drive root, exit early to avoid + // unnecessary work + ret.root = ret.dir = path; + return ret; + } + rootEnd = 3; + } + } else { + // `path` contains just a drive root, exit early to avoid + // unnecessary work + ret.root = ret.dir = path; + return ret; + } + } + } + } else if (isPathSeparator(code)) { + // `path` contains just a path separator, exit early to avoid + // unnecessary work + ret.root = ret.dir = path; + return ret; + } + + if (rootEnd > 0) { + ret.root = path.slice(0, rootEnd); + } + + let startDot = -1; + let startPart = rootEnd; + let end = -1; + let matchedSlash = true; + let i = path.length - 1; + + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + + // Get non-dir info + for (; i >= rootEnd; --i) { + code = path.charCodeAt(i); + if (isPathSeparator(code)) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) { + startDot = i; + } + else if (preDotState !== 1) { + preDotState = 1; + } + } else if (startDot !== -1) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } + + if (startDot === -1 || + end === -1 || + // We saw a non-dot character immediately before the dot + preDotState === 0 || + // The (right-most) trimmed path component is exactly '..' + (preDotState === 1 && + startDot === end - 1 && + startDot === startPart + 1)) { + if (end !== -1) { + ret.base = ret.name = path.slice(startPart, end); + } + } else { + ret.name = path.slice(startPart, startDot); + ret.base = path.slice(startPart, end); + ret.ext = path.slice(startDot, end); + } + + // If the directory is the root, use the entire root as the `dir` including + // the trailing slash if any (`C:\abc` -> `C:\`). Otherwise, strip out the + // trailing slash (`C:\abc\def` -> `C:\abc`). + if (startPart > 0 && startPart !== rootEnd) { + ret.dir = path.slice(0, startPart - 1); + } + else { + ret.dir = ret.root; + } + + return ret; + }, + + sep: '\\', + delimiter: ';', + win32: null, + posix: null +}; + +export const posix: IPath = { + // path.resolve([from ...], to) + resolve(...pathSegments: string[]): string { + let resolvedPath = ''; + let resolvedAbsolute = false; + + for (let i = pathSegments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + let path; + if (i >= 0) { + path = pathSegments[i]; + } + else { + path = process.cwd(); + } + + validateString(path, 'path'); + + // Skip empty entries + if (path.length === 0) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/', + isPosixPathSeparator); + + if (resolvedAbsolute) { + if (resolvedPath.length > 0) { + return '/' + resolvedPath; + } + else { + return '/'; + } + } else if (resolvedPath.length > 0) { + return resolvedPath; + } else { + return '.'; + } + }, + + normalize(path: string): string { + validateString(path, 'path'); + + if (path.length === 0) { + return '.'; + } + + const isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; + const trailingSeparator = + path.charCodeAt(path.length - 1) === CHAR_FORWARD_SLASH; + + // Normalize the path + path = normalizeString(path, !isAbsolute, '/', isPosixPathSeparator); + + if (path.length === 0 && !isAbsolute) { + path = '.'; + } + if (path.length > 0 && trailingSeparator) { + path += '/'; + } + + if (isAbsolute) { + return '/' + path; + } + return path; + }, + + isAbsolute(path: string): boolean { + validateString(path, 'path'); + return path.length > 0 && path.charCodeAt(0) === CHAR_FORWARD_SLASH; + }, + + join(...paths: string[]): string { + if (paths.length === 0) { + return '.'; + } + let joined; + for (let i = 0; i < paths.length; ++i) { + const arg = arguments[i]; + validateString(arg, 'path'); + if (arg.length > 0) { + if (joined === undefined) { + joined = arg; + } + else { + joined += '/' + arg; + } + } + } + if (joined === undefined) { + return '.'; + } + return posix.normalize(joined); + }, + + relative(from: string, to: string): string { + validateString(from, 'from'); + validateString(to, 'to'); + + if (from === to) { + return ''; + } + + from = posix.resolve(from); + to = posix.resolve(to); + + if (from === to) { + return ''; + } + + // Trim any leading backslashes + let fromStart = 1; + for (; fromStart < from.length; ++fromStart) { + if (from.charCodeAt(fromStart) !== CHAR_FORWARD_SLASH) { + break; + } + } + const fromEnd = from.length; + const fromLen = (fromEnd - fromStart); + + // Trim any leading backslashes + let toStart = 1; + for (; toStart < to.length; ++toStart) { + if (to.charCodeAt(toStart) !== CHAR_FORWARD_SLASH) { + break; + } + } + const toEnd = to.length; + const toLen = (toEnd - toStart); + + // Compare paths to find the longest common path from root + const length = (fromLen < toLen ? fromLen : toLen); + let lastCommonSep = -1; + let i = 0; + for (; i <= length; ++i) { + if (i === length) { + if (toLen > length) { + if (to.charCodeAt(toStart + i) === CHAR_FORWARD_SLASH) { + // We get here if `from` is the exact base path for `to`. + // For example: from='/foo/bar'; to='/foo/bar/baz' + return to.slice(toStart + i + 1); + } else if (i === 0) { + // We get here if `from` is the root + // For example: from='/'; to='/foo' + return to.slice(toStart + i); + } + } else if (fromLen > length) { + if (from.charCodeAt(fromStart + i) === CHAR_FORWARD_SLASH) { + // We get here if `to` is the exact base path for `from`. + // For example: from='/foo/bar/baz'; to='/foo/bar' + lastCommonSep = i; + } else if (i === 0) { + // We get here if `to` is the root. + // For example: from='/foo'; to='/' + lastCommonSep = 0; + } + } + break; + } + const fromCode = from.charCodeAt(fromStart + i); + const toCode = to.charCodeAt(toStart + i); + if (fromCode !== toCode) { + break; + } + else if (fromCode === CHAR_FORWARD_SLASH) { + lastCommonSep = i; + } + } + + let out = ''; + // Generate the relative path based on the path difference between `to` + // and `from` + for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { + if (i === fromEnd || from.charCodeAt(i) === CHAR_FORWARD_SLASH) { + if (out.length === 0) { + out += '..'; + } + else { + out += '/..'; + } + } + } + + // Lastly, append the rest of the destination (`to`) path that comes after + // the common path parts + if (out.length > 0) { + return out + to.slice(toStart + lastCommonSep); + } + else { + toStart += lastCommonSep; + if (to.charCodeAt(toStart) === CHAR_FORWARD_SLASH) { + ++toStart; + } + return to.slice(toStart); + } + }, + + toNamespacedPath(path: string): string { + // Non-op on posix systems + return path; + }, + + dirname(path: string): string { + validateString(path, 'path'); + if (path.length === 0) { + return '.'; + } + const hasRoot = path.charCodeAt(0) === CHAR_FORWARD_SLASH; + let end = -1; + let matchedSlash = true; + for (let i = path.length - 1; i >= 1; --i) { + if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) { + if (!matchedSlash) { + end = i; + break; + } + } else { + // We saw the first non-path separator + matchedSlash = false; + } + } + + if (end === -1) { + return hasRoot ? '/' : '.'; + } + if (hasRoot && end === 1) { + return '//'; + } + return path.slice(0, end); + }, + + basename(path: string, ext?: string): string { + if (ext !== undefined) { + validateString(ext, 'ext'); + } + validateString(path, 'path'); + + let start = 0; + let end = -1; + let matchedSlash = true; + let i; + + if (ext !== undefined && ext.length > 0 && ext.length <= path.length) { + if (ext.length === path.length && ext === path) { + return ''; + } + let extIdx = ext.length - 1; + let firstNonSlashEnd = -1; + for (i = path.length - 1; i >= 0; --i) { + const code = path.charCodeAt(i); + if (code === CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; + } + } else { + if (firstNonSlashEnd === -1) { + // We saw the first non-path separator, remember this index in case + // we need it if the extension ends up not matching + matchedSlash = false; + firstNonSlashEnd = i + 1; + } + if (extIdx >= 0) { + // Try to match the explicit extension + if (code === ext.charCodeAt(extIdx)) { + if (--extIdx === -1) { + // We matched the extension, so mark this as the end of our path + // component + end = i; + } + } else { + // Extension does not match, so our result is the entire path + // component + extIdx = -1; + end = firstNonSlashEnd; + } + } + } + } + + if (start === end) { + end = firstNonSlashEnd; + } + else if (end === -1) { + end = path.length; + } + return path.slice(start, end); + } else { + for (i = path.length - 1; i >= 0; --i) { + if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; + } + } else if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // path component + matchedSlash = false; + end = i + 1; + } + } + + if (end === -1) { + return ''; + } + return path.slice(start, end); + } + }, + + extname(path: string): string { + validateString(path, 'path'); + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + for (let i = path.length - 1; i >= 0; --i) { + const code = path.charCodeAt(i); + if (code === CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) { + startDot = i; + } + else if (preDotState !== 1) { + preDotState = 1; + } + } else if (startDot !== -1) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } + + if (startDot === -1 || + end === -1 || + // We saw a non-dot character immediately before the dot + preDotState === 0 || + // The (right-most) trimmed path component is exactly '..' + (preDotState === 1 && + startDot === end - 1 && + startDot === startPart + 1)) { + return ''; + } + return path.slice(startDot, end); + }, + + format(pathObject): string { + if (pathObject === null || typeof pathObject !== 'object') { + throw new ErrorInvalidArgType('pathObject', 'Object', pathObject); + } + + return _format('/', pathObject); + }, + + parse(path: string): ParsedPath { + validateString(path, 'path'); + + const ret = { root: '', dir: '', base: '', ext: '', name: '' }; + if (path.length === 0) { + return ret; + } + const isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; + let start; + if (isAbsolute) { + ret.root = '/'; + start = 1; + } else { + start = 0; + } + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; + let i = path.length - 1; + + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + + // Get non-dir info + for (; i >= start; --i) { + const code = path.charCodeAt(i); + if (code === CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) { + startDot = i; + } + else if (preDotState !== 1) { + preDotState = 1; + } + } else if (startDot !== -1) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } + + if (startDot === -1 || + end === -1 || + // We saw a non-dot character immediately before the dot + preDotState === 0 || + // The (right-most) trimmed path component is exactly '..' + (preDotState === 1 && + startDot === end - 1 && + startDot === startPart + 1)) { + if (end !== -1) { + if (startPart === 0 && isAbsolute) { + ret.base = ret.name = path.slice(1, end); + } + else { + ret.base = ret.name = path.slice(startPart, end); + } + } + } else { + if (startPart === 0 && isAbsolute) { + ret.name = path.slice(1, startDot); + ret.base = path.slice(1, end); + } else { + ret.name = path.slice(startPart, startDot); + ret.base = path.slice(startPart, end); + } + ret.ext = path.slice(startDot, end); + } + + if (startPart > 0) { + ret.dir = path.slice(0, startPart - 1); + } + else if (isAbsolute) { + ret.dir = '/'; + } + + return ret; + }, + + sep: '/', + delimiter: ':', + win32: null, + posix: null +}; + +posix.win32 = win32.win32 = win32; +posix.posix = win32.posix = posix; + +export const normalize = (process.platform === 'win32' ? win32.normalize : posix.normalize); +export const isAbsolute = (process.platform === 'win32' ? win32.isAbsolute : posix.isAbsolute); +export const join = (process.platform === 'win32' ? win32.join : posix.join); +export const resolve = (process.platform === 'win32' ? win32.resolve : posix.resolve); +export const relative = (process.platform === 'win32' ? win32.relative : posix.relative); +export const dirname = (process.platform === 'win32' ? win32.dirname : posix.dirname); +export const basename = (process.platform === 'win32' ? win32.basename : posix.basename); +export const extname = (process.platform === 'win32' ? win32.extname : posix.extname); +export const format = (process.platform === 'win32' ? win32.format : posix.format); +export const parse = (process.platform === 'win32' ? win32.parse : posix.parse); +export const toNamespacedPath = (process.platform === 'win32' ? win32.toNamespacedPath : posix.toNamespacedPath); +export const sep = (process.platform === 'win32' ? win32.sep : posix.sep); +export const delimiter = (process.platform === 'win32' ? win32.delimiter : posix.delimiter); diff --git a/src/vs/base/common/paths.ts b/src/vs/base/common/paths.ts deleted file mode 100644 index d96b7517082..00000000000 --- a/src/vs/base/common/paths.ts +++ /dev/null @@ -1,405 +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 { isWindows } from 'vs/base/common/platform'; -import { startsWithIgnoreCase, equalsIgnoreCase } from 'vs/base/common/strings'; -import { CharCode } from 'vs/base/common/charCode'; - -/** - * The forward slash path separator. - */ -export const sep = '/'; - -/** - * The native path separator depending on the OS. - */ -export const nativeSep = isWindows ? '\\' : '/'; - -/** - * @param path the path to get the dirname from - * @param separator the separator to use - * @returns the directory name of a path. - * - */ -export function dirname(path: string, separator = nativeSep): string { - const idx = ~path.lastIndexOf('/') || ~path.lastIndexOf('\\'); - if (idx === 0) { - return '.'; - } else if (~idx === 0) { - return path[0]; - } else if (~idx === path.length - 1) { - return dirname(path.substring(0, path.length - 1)); - } else { - let res = path.substring(0, ~idx); - if (isWindows && res[res.length - 1] === ':') { - res += separator; // make sure drive letters end with backslash - } - return res; - } -} - -/** - * @returns the base name of a path. - */ -export function basename(path: string): string { - const idx = ~path.lastIndexOf('/') || ~path.lastIndexOf('\\'); - if (idx === 0) { - return path; - } else if (~idx === path.length - 1) { - return basename(path.substring(0, path.length - 1)); - } else { - return path.substr(~idx + 1); - } -} - -/** - * @returns `.far` from `boo.far` or the empty string. - */ -export function extname(path: string): string { - path = basename(path); - const idx = ~path.lastIndexOf('.'); - return idx ? path.substring(~idx) : ''; -} - -const _posixBadPath = /(\/\.\.?\/)|(\/\.\.?)$|^(\.\.?\/)|(\/\/+)|(\\)/; -const _winBadPath = /(\\\.\.?\\)|(\\\.\.?)$|^(\.\.?\\)|(\\\\+)|(\/)/; - -function _isNormal(path: string, win: boolean): boolean { - return win - ? !_winBadPath.test(path) - : !_posixBadPath.test(path); -} - -export function normalize(path: undefined, toOSPath?: boolean): undefined; -export function normalize(path: null, toOSPath?: boolean): null; -export function normalize(path: string, toOSPath?: boolean): string; -export function normalize(path: string | null | undefined, toOSPath?: boolean): string | null | undefined { - - if (path === null || path === undefined) { - return path; - } - - const len = path.length; - if (len === 0) { - return '.'; - } - - const wantsBackslash = !!(isWindows && toOSPath); - if (_isNormal(path, wantsBackslash)) { - return path; - } - - const sep = wantsBackslash ? '\\' : '/'; - const root = getRoot(path, sep); - - // skip the root-portion of the path - let start = root.length; - let skip = false; - let res = ''; - - for (let end = root.length; end <= len; end++) { - - // either at the end or at a path-separator character - if (end === len || path.charCodeAt(end) === CharCode.Slash || path.charCodeAt(end) === CharCode.Backslash) { - - if (streql(path, start, end, '..')) { - // skip current and remove parent (if there is already something) - let prev_start = res.lastIndexOf(sep); - let prev_part = res.slice(prev_start + 1); - if ((root || prev_part.length > 0) && prev_part !== '..') { - res = prev_start === -1 ? '' : res.slice(0, prev_start); - skip = true; - } - } else if (streql(path, start, end, '.') && (root || res || end < len - 1)) { - // skip current (if there is already something or if there is more to come) - skip = true; - } - - if (!skip) { - let part = path.slice(start, end); - if (res !== '' && res[res.length - 1] !== sep) { - res += sep; - } - res += part; - } - start = end + 1; - skip = false; - } - } - - return root + res; -} - -function streql(value: string, start: number, end: number, other: string): boolean { - return start + other.length === end && value.indexOf(other, start) === start; -} - -/** - * Computes the _root_ this path, like `getRoot('c:\files') === c:\`, - * `getRoot('files:///files/path') === files:///`, - * or `getRoot('\\server\shares\path') === \\server\shares\` - */ -export function getRoot(path: string, sep: string = '/'): string { - - if (!path) { - return ''; - } - - let len = path.length; - let code = path.charCodeAt(0); - if (code === CharCode.Slash || code === CharCode.Backslash) { - - code = path.charCodeAt(1); - if (code === CharCode.Slash || code === CharCode.Backslash) { - // UNC candidate \\localhost\shares\ddd - // ^^^^^^^^^^^^^^^^^^^ - code = path.charCodeAt(2); - if (code !== CharCode.Slash && code !== CharCode.Backslash) { - let pos = 3; - let start = pos; - for (; pos < len; pos++) { - code = path.charCodeAt(pos); - if (code === CharCode.Slash || code === CharCode.Backslash) { - break; - } - } - code = path.charCodeAt(pos + 1); - if (start !== pos && code !== CharCode.Slash && code !== CharCode.Backslash) { - pos += 1; - for (; pos < len; pos++) { - code = path.charCodeAt(pos); - if (code === CharCode.Slash || code === CharCode.Backslash) { - return path.slice(0, pos + 1) // consume this separator - .replace(/[\\/]/g, sep); - } - } - } - } - } - - // /user/far - // ^ - return sep; - - } else if ((code >= CharCode.A && code <= CharCode.Z) || (code >= CharCode.a && code <= CharCode.z)) { - // check for windows drive letter c:\ or c: - - if (path.charCodeAt(1) === CharCode.Colon) { - code = path.charCodeAt(2); - if (code === CharCode.Slash || code === CharCode.Backslash) { - // C:\fff - // ^^^ - return path.slice(0, 2) + sep; - } else { - // C: - // ^^ - return path.slice(0, 2); - } - } - } - - // check for URI - // scheme://authority/path - // ^^^^^^^^^^^^^^^^^^^ - let pos = path.indexOf('://'); - if (pos !== -1) { - pos += 3; // 3 -> "://".length - for (; pos < len; pos++) { - code = path.charCodeAt(pos); - if (code === CharCode.Slash || code === CharCode.Backslash) { - return path.slice(0, pos + 1); // consume this separator - } - } - } - - return ''; -} - -export const join: (...parts: string[]) => string = function () { - // Not using a function with var-args because of how TS compiles - // them to JS - it would result in 2*n runtime cost instead - // of 1*n, where n is parts.length. - - let value = ''; - for (let i = 0; i < arguments.length; i++) { - let part = arguments[i]; - if (i > 0) { - // add the separater between two parts unless - // there already is one - let last = value.charCodeAt(value.length - 1); - if (last !== CharCode.Slash && last !== CharCode.Backslash) { - let next = part.charCodeAt(0); - if (next !== CharCode.Slash && next !== CharCode.Backslash) { - - value += sep; - } - } - } - value += part; - } - - return normalize(value); -}; - - -/** - * Check if the path follows this pattern: `\\hostname\sharename`. - * - * @see https://msdn.microsoft.com/en-us/library/gg465305.aspx - * @return A boolean indication if the path is a UNC path, on none-windows - * always false. - */ -export function isUNC(path: string): boolean { - if (!isWindows) { - // UNC is a windows concept - return false; - } - - if (!path || path.length < 5) { - // at least \\a\b - return false; - } - - let code = path.charCodeAt(0); - if (code !== CharCode.Backslash) { - return false; - } - code = path.charCodeAt(1); - if (code !== CharCode.Backslash) { - return false; - } - let pos = 2; - let start = pos; - for (; pos < path.length; pos++) { - code = path.charCodeAt(pos); - if (code === CharCode.Backslash) { - break; - } - } - if (start === pos) { - return false; - } - code = path.charCodeAt(pos + 1); - if (isNaN(code) || code === CharCode.Backslash) { - return false; - } - return true; -} - -// Reference: https://en.wikipedia.org/wiki/Filename -const INVALID_FILE_CHARS = isWindows ? /[\\/:\*\?"<>\|]/g : /[\\/]/g; -const WINDOWS_FORBIDDEN_NAMES = /^(con|prn|aux|clock\$|nul|lpt[0-9]|com[0-9])$/i; -export function isValidBasename(name: string | null | undefined): boolean { - if (!name || name.length === 0 || /^\s+$/.test(name)) { - return false; // require a name that is not just whitespace - } - - INVALID_FILE_CHARS.lastIndex = 0; // the holy grail of software development - if (INVALID_FILE_CHARS.test(name)) { - return false; // check for certain invalid file characters - } - - if (isWindows && WINDOWS_FORBIDDEN_NAMES.test(name)) { - return false; // check for certain invalid file names - } - - if (name === '.' || name === '..') { - return false; // check for reserved values - } - - if (isWindows && name[name.length - 1] === '.') { - return false; // Windows: file cannot end with a "." - } - - if (isWindows && name.length !== name.trim().length) { - return false; // Windows: file cannot end with a whitespace - } - - return true; -} - -export function isEqual(pathA: string, pathB: string, ignoreCase?: boolean): boolean { - const identityEquals = (pathA === pathB); - if (!ignoreCase || identityEquals) { - return identityEquals; - } - - if (!pathA || !pathB) { - return false; - } - - return equalsIgnoreCase(pathA, pathB); -} - -export function isEqualOrParent(path: string, candidate: string, ignoreCase?: boolean, separator = nativeSep): boolean { - if (path === candidate) { - return true; - } - - if (!path || !candidate) { - return false; - } - - if (candidate.length > path.length) { - return false; - } - - if (ignoreCase) { - const beginsWith = startsWithIgnoreCase(path, candidate); - if (!beginsWith) { - return false; - } - - if (candidate.length === path.length) { - return true; // same path, different casing - } - - let sepOffset = candidate.length; - if (candidate.charAt(candidate.length - 1) === separator) { - sepOffset--; // adjust the expected sep offset in case our candidate already ends in separator character - } - - return path.charAt(sepOffset) === separator; - } - - if (candidate.charAt(candidate.length - 1) !== separator) { - candidate += separator; - } - - return path.indexOf(candidate) === 0; -} - -/** - * Adapted from Node's path.isAbsolute functions - */ -export function isAbsolute(path: string): boolean { - return isWindows ? - isAbsolute_win32(path) : - isAbsolute_posix(path); -} - -export function isAbsolute_win32(path: string): boolean { - if (!path) { - return false; - } - - const char0 = path.charCodeAt(0); - if (char0 === CharCode.Slash || char0 === CharCode.Backslash) { - return true; - } else if ((char0 >= CharCode.A && char0 <= CharCode.Z) || (char0 >= CharCode.a && char0 <= CharCode.z)) { - if (path.length > 2 && path.charCodeAt(1) === CharCode.Colon) { - const char2 = path.charCodeAt(2); - if (char2 === CharCode.Slash || char2 === CharCode.Backslash) { - return true; - } - } - } - - return false; -} - -export function isAbsolute_posix(path: string): boolean { - return !!(path && path.charCodeAt(0) === CharCode.Slash); -} diff --git a/src/vs/base/common/performance.d.ts b/src/vs/base/common/performance.d.ts index dfdb1251598..657f250d8b3 100644 --- a/src/vs/base/common/performance.d.ts +++ b/src/vs/base/common/performance.d.ts @@ -4,22 +4,18 @@ *--------------------------------------------------------------------------------------------*/ export interface PerformanceEntry { - readonly type: 'mark' | 'measure'; readonly name: string; - readonly startTime: number; - readonly duration: number; + readonly timestamp: number; } export function mark(name: string): void; -export function measure(name: string, from?: string, to?: string): PerformanceEntry; - /** * All entries filtered by type and sorted by `startTime`. */ -export function getEntries(type: 'mark' | 'measure'): PerformanceEntry[]; +export function getEntries(): PerformanceEntry[]; -export function getEntry(type: 'mark' | 'measure', name: string): PerformanceEntry; +export function getEntry(name: string): PerformanceEntry; export function getDuration(from: string, to: string): number; diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index 14c5a33e72e..2bc77108620 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -5,137 +5,73 @@ 'use strict'; -/*global define*/ +//@ts-check -// This module can be loaded in an amd and commonjs-context. -// Because we want both instances to use the same perf-data -// we store them globally -// stores data as 'type','name','startTime','duration' +function _factory(sharedObj) { -if (typeof define !== "function" && typeof module === "object" && typeof module.exports === "object") { - // this is commonjs, fake amd - global.define = function (dep, callback) { - module.exports = callback(); - global.define = undefined; - }; -} + sharedObj._performanceEntries = sharedObj._performanceEntries || []; -define([], function () { - - var _global = this; - if (typeof global !== 'undefined') { - _global = global; - } - _global._performanceEntries = _global._performanceEntries || []; - - // const _now = global.performance && performance.now ? performance.now : Date.now - const _now = Date.now; + const _dataLen = 2; + const _timeStamp = typeof console.timeStamp === 'function' ? console.timeStamp.bind(console) : () => { }; function importEntries(entries) { - global._performanceEntries.splice(0, 0, ...entries); + sharedObj._performanceEntries.splice(0, 0, ...entries); } function exportEntries() { - return global._performanceEntries.slice(0); + return sharedObj._performanceEntries.slice(0); } - function getEntries(type, name) { + function getEntries() { const result = []; - const entries = global._performanceEntries; - for (let i = 0; i < entries.length; i += 5) { - if (entries[i] === type && (name === undefined || entries[i + 1] === name)) { - result.push({ - type: entries[i], - name: entries[i + 1], - startTime: entries[i + 2], - duration: entries[i + 3], - seq: entries[i + 4], - }); - } + const entries = sharedObj._performanceEntries; + for (let i = 0; i < entries.length; i += _dataLen) { + result.push({ + name: entries[i], + timestamp: entries[i + 1], + }); } - - return result.sort((a, b) => { - return a.startTime - b.startTime || a.seq - b.seq; - }); + return result; } - function getEntry(type, name) { - const entries = global._performanceEntries; - for (let i = 0; i < entries.length; i += 5) { - if (entries[i] === type && entries[i + 1] === name) { + function getEntry(name) { + const entries = sharedObj._performanceEntries; + for (let i = 0; i < entries.length; i += _dataLen) { + if (entries[i] === name) { return { - type: entries[i], - name: entries[i + 1], - startTime: entries[i + 2], - duration: entries[i + 3], - seq: entries[i + 4], + name: entries[i], + timestamp: entries[i + 1], }; } } } function getDuration(from, to) { - const entries = global._performanceEntries; + const entries = sharedObj._performanceEntries; let target = to; - let endTime = 0; - for (let i = entries.length - 1; i >= 0; i -= 5) { - if (entries[i - 3] === target) { + let endIndex = 0; + for (let i = entries.length - _dataLen; i >= 0; i -= _dataLen) { + if (entries[i] === target) { if (target === to) { // found `to` (end of interval) - endTime = entries[i - 2]; + endIndex = i; target = from; } else { - return endTime - entries[i - 2]; + // found `from` (start of interval) + return entries[endIndex + 1] - entries[i + 1]; } } } return 0; } - let seq = 0; - function mark(name) { - global._performanceEntries.push('mark', name, _now(), 0, seq++); - if (typeof console.timeStamp === 'function') { - console.timeStamp(name); - } + sharedObj._performanceEntries.push(name, Date.now()); + _timeStamp(name); } - function measure(name, from, to) { - - let startTime; - let duration; - let now = _now(); - - if (!from) { - startTime = now; - } else { - startTime = _getLastStartTime(from); - } - - if (!to) { - duration = now - startTime; - } else { - duration = _getLastStartTime(to) - startTime; - } - - global._performanceEntries.push('measure', name, startTime, duration); - } - - function _getLastStartTime(name) { - const entries = global._performanceEntries; - for (let i = entries.length - 1; i >= 0; i -= 5) { - if (entries[i - 3] === name) { - return entries[i - 2]; - } - } - - throw new Error(name + ' not found'); - } - - var exports = { + const exports = { mark: mark, - measure: measure, getEntries: getEntries, getEntry: getEntry, getDuration: getDuration, @@ -144,4 +80,29 @@ define([], function () { }; return exports; -}); +} + +// This module can be loaded in an amd and commonjs-context. +// Because we want both instances to use the same perf-data +// we store them globally + +let sharedObj; +if (typeof global === 'object') { + // nodejs + sharedObj = global; +} else if (typeof self === 'object') { + // browser + sharedObj = self; +} else { + sharedObj = {}; +} + +if (typeof define === 'function') { + // amd + define([], function () { return _factory(sharedObj); }); +} else if (typeof module === "object" && typeof module.exports === "object") { + // commonjs + module.exports = _factory(sharedObj); +} else { + // invalid context... +} diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts index 864c6bdc620..d7371552d30 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts @@ -3,14 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +const LANGUAGE_DEFAULT = 'en'; + let _isWindows = false; let _isMacintosh = false; let _isLinux = false; let _isNative = false; let _isWeb = false; let _locale: string | undefined = undefined; -let _language: string | undefined = undefined; +let _language: string = LANGUAGE_DEFAULT; let _translationsConfigFile: string | undefined = undefined; +let _userAgent: string | undefined = undefined; interface NLSConfig { locale: string; @@ -32,26 +35,24 @@ interface INodeProcess { }; type?: string; } -declare let process: INodeProcess; -declare let global: any; +declare const process: INodeProcess; +declare const global: any; interface INavigator { userAgent: string; language: string; } -declare let navigator: INavigator; -declare let self: any; - -export const LANGUAGE_DEFAULT = 'en'; +declare const navigator: INavigator; +declare const self: any; const isElectronRenderer = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions.electron !== 'undefined' && process.type === 'renderer'); // OS detection if (typeof navigator === 'object' && !isElectronRenderer) { - const userAgent = navigator.userAgent; - _isWindows = userAgent.indexOf('Windows') >= 0; - _isMacintosh = userAgent.indexOf('Macintosh') >= 0; - _isLinux = userAgent.indexOf('Linux') >= 0; + _userAgent = navigator.userAgent; + _isWindows = _userAgent.indexOf('Windows') >= 0; + _isMacintosh = _userAgent.indexOf('Macintosh') >= 0; + _isLinux = _userAgent.indexOf('Linux') >= 0; _isWeb = true; _locale = navigator.language; _language = _locale; @@ -108,6 +109,7 @@ export const isLinux = _isLinux; export const isNative = _isNative; export const isWeb = _isWeb; export const platform = _platform; +export const userAgent = _userAgent; export function isRootUser(): boolean { return _isNative && !_isWindows && (process.getuid() === 0); @@ -120,6 +122,27 @@ export function isRootUser(): boolean { */ export const language = _language; +export namespace Language { + + export function value(): string { + return language; + } + + export function isDefaultVariant(): boolean { + if (language.length === 2) { + return language === 'en'; + } else if (language.length >= 3) { + return language[0] === 'e' && language[1] === 'n' && language[2] === '-'; + } else { + return false; + } + } + + export function isDefault(): boolean { + return language === 'en'; + } +} + /** * The OS locale or the locale specified by --locale. The format of * the string is all lower case (e.g. zh-tw for Traditional @@ -155,14 +178,3 @@ export const enum OperatingSystem { Linux = 3 } export const OS = (_isMacintosh ? OperatingSystem.Macintosh : (_isWindows ? OperatingSystem.Windows : OperatingSystem.Linux)); - -export const enum AccessibilitySupport { - /** - * This should be the browser case where it is not known if a screen reader is attached or no. - */ - Unknown = 0, - - Disabled = 1, - - Enabled = 2 -} diff --git a/src/vs/base/common/process.ts b/src/vs/base/common/process.ts new file mode 100644 index 00000000000..a8447d58eea --- /dev/null +++ b/src/vs/base/common/process.ts @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { isWindows, isMacintosh, setImmediate } from 'vs/base/common/platform'; + +interface IProcess { + platform: string; + env: object; + + cwd(): string; + nextTick(callback: (...args: any[]) => void): number; +} + +declare const process: IProcess; +const safeProcess: IProcess = (typeof process === 'undefined') ? { + cwd(): string { return '/'; }, + env: Object.create(null), + get platform(): string { return isWindows ? 'win32' : isMacintosh ? 'darwin' : 'linux'; }, + nextTick(callback: (...args: any[]) => void): number { return setImmediate(callback); } +} : process; + +export const cwd = safeProcess.cwd; +export const env = safeProcess.env; +export const platform = safeProcess.platform; +export const nextTick = safeProcess.nextTick; diff --git a/src/vs/base/common/processes.ts b/src/vs/base/common/processes.ts index 7eef74d894f..c52f7b3774f 100644 --- a/src/vs/base/common/processes.ts +++ b/src/vs/base/common/processes.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { IProcessEnvironment } from 'vs/base/common/platform'; + /** * Options to be passed to the external program or shell. */ @@ -84,3 +86,41 @@ export const enum TerminateResponseCode { AccessDenied = 2, ProcessNotFound = 3, } + +export interface ProcessItem { + name: string; + cmd: string; + pid: number; + ppid: number; + load: number; + mem: number; + + children?: ProcessItem[]; +} + +/** + * Sanitizes a VS Code process environment by removing all Electron/VS Code-related values. + */ +export function sanitizeProcessEnvironment(env: IProcessEnvironment, ...preserve: string[]): void { + const set = preserve.reduce((set, key) => { + set[key] = true; + return set; + }, {} as Record); + const keysToRemove = [ + /^ELECTRON_.+$/, + /^GOOGLE_API_KEY$/, + /^VSCODE_.+$/, + /^SNAP(|_.*)$/ + ]; + const envKeys = Object.keys(env); + envKeys + .filter(key => !set[key]) + .forEach(envKey => { + for (let i = 0; i < keysToRemove.length; i++) { + if (envKey.search(keysToRemove[i]) !== -1) { + delete env[envKey]; + break; + } + } + }); +} diff --git a/src/vs/base/common/resources.ts b/src/vs/base/common/resources.ts index d3170eb406b..8ccc9567737 100644 --- a/src/vs/base/common/resources.ts +++ b/src/vs/base/common/resources.ts @@ -3,12 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as paths from 'vs/base/common/paths'; +import * as extpath from 'vs/base/common/extpath'; +import * as paths from 'vs/base/common/path'; import { URI } from 'vs/base/common/uri'; import { equalsIgnoreCase } from 'vs/base/common/strings'; import { Schemas } from 'vs/base/common/network'; import { isLinux, isWindows } from 'vs/base/common/platform'; import { CharCode } from 'vs/base/common/charCode'; +import { ParsedExpression, IExpression, parse } from 'vs/base/common/glob'; +import { TernarySearchTree } from 'vs/base/common/map'; export function getComparisonKey(resource: URI): string { return hasToIgnoreCase(resource) ? resource.toString().toLowerCase() : resource.toString(); @@ -32,22 +35,24 @@ export function basenameOrAuthority(resource: URI): string { export function isEqualOrParent(base: URI, parentCandidate: URI, ignoreCase = hasToIgnoreCase(base)): boolean { if (base.scheme === parentCandidate.scheme) { if (base.scheme === Schemas.file) { - return paths.isEqualOrParent(fsPath(base), fsPath(parentCandidate), ignoreCase); + return extpath.isEqualOrParent(originalFSPath(base), originalFSPath(parentCandidate), ignoreCase); } - if (isEqualAuthority(base.authority, parentCandidate.authority, ignoreCase)) { - return paths.isEqualOrParent(base.path, parentCandidate.path, ignoreCase, '/'); + if (isEqualAuthority(base.authority, parentCandidate.authority)) { + return extpath.isEqualOrParent(base.path, parentCandidate.path, ignoreCase, '/'); } } return false; } -function isEqualAuthority(a1: string, a2: string, ignoreCase?: boolean) { - return a1 === a2 || ignoreCase && a1 && a2 && equalsIgnoreCase(a1, a2); +/** + * Tests wheter the two authorities are the same + */ +export function isEqualAuthority(a1: string, a2: string) { + return a1 === a2 || equalsIgnoreCase(a1, a2); } export function isEqual(first: URI | undefined, second: URI | undefined, ignoreCase = hasToIgnoreCase(first)): boolean { - const identityEquals = (first === second); - if (identityEquals) { + if (first === second) { return true; } @@ -55,15 +60,20 @@ export function isEqual(first: URI | undefined, second: URI | undefined, ignoreC return false; } - if (ignoreCase) { - return equalsIgnoreCase(first.toString(), second.toString()); + if (first.scheme !== second.scheme || !isEqualAuthority(first.authority, second.authority)) { + return false; } - return first.toString() === second.toString(); + const p1 = first.path || '/', p2 = second.path || '/'; + return p1 === p2 || ignoreCase && equalsIgnoreCase(p1 || '/', p2 || '/'); } export function basename(resource: URI): string { - return paths.basename(resource.path); + return paths.posix.basename(resource.path); +} + +export function extname(resource: URI): string { + return paths.posix.extname(resource.path); } /** @@ -72,13 +82,17 @@ export function basename(resource: URI): string { * @param resource The input URI. * @returns The URI representing the directory of the input URI. */ -export function dirname(resource: URI): URI | null { - if (resource.scheme === Schemas.file) { - return URI.file(paths.dirname(fsPath(resource))); +export function dirname(resource: URI): URI { + if (resource.path.length === 0) { + return resource; } - let dirname = paths.dirname(resource.path, '/'); + if (resource.scheme === Schemas.file) { + return URI.file(paths.dirname(originalFSPath(resource))); + } + let dirname = paths.posix.dirname(resource.path); if (resource.authority && dirname.length && dirname.charCodeAt(0) !== CharCode.Slash) { - return null; // If a URI contains an authority component, then the path component must either be empty or begin with a CharCode.Slash ("/") character + console.error(`dirname("${resource.toString})) resulted in a relative path`); + dirname = '/'; // If a URI contains an authority component, then the path component must either be empty or begin with a CharCode.Slash ("/") character } return resource.with({ path: dirname @@ -86,18 +100,18 @@ export function dirname(resource: URI): URI | null { } /** - * Join a URI path with a path fragment and normalizes the resulting path. + * Join a URI path with path fragments and normalizes the resulting path. * * @param resource The input URI. * @param pathFragment The path fragment to add to the URI path. * @returns The resulting URI. */ -export function joinPath(resource: URI, pathFragment: string): URI { +export function joinPath(resource: URI, ...pathFragment: string[]): URI { let joinedPath: string; if (resource.scheme === Schemas.file) { - joinedPath = URI.file(paths.join(fsPath(resource), pathFragment)).path; + joinedPath = URI.file(paths.join(originalFSPath(resource), ...pathFragment)).path; } else { - joinedPath = paths.join(resource.path, pathFragment); + joinedPath = paths.posix.join(resource.path || '/', ...pathFragment); } return resource.with({ path: joinedPath @@ -111,11 +125,14 @@ export function joinPath(resource: URI, pathFragment: string): URI { * @returns The URI with the normalized path. */ export function normalizePath(resource: URI): URI { + if (!resource.path.length) { + return resource; + } let normalizedPath: string; if (resource.scheme === Schemas.file) { - normalizedPath = URI.file(paths.normalize(fsPath(resource))).path; + normalizedPath = URI.file(paths.normalize(originalFSPath(resource))).path; } else { - normalizedPath = paths.normalize(resource.path); + normalizedPath = paths.posix.normalize(resource.path); } return resource.with({ path: normalizedPath @@ -126,21 +143,22 @@ export function normalizePath(resource: URI): URI { * Returns the fsPath of an URI where the drive letter is not normalized. * See #56403. */ -export function fsPath(uri: URI): string { +export function originalFSPath(uri: URI): string { let value: string; - if (uri.authority && uri.path.length > 1 && uri.scheme === 'file') { + const uriPath = uri.path; + if (uri.authority && uriPath.length > 1 && uri.scheme === Schemas.file) { // unc path: file://shares/c$/far/boo - value = `//${uri.authority}${uri.path}`; + value = `//${uri.authority}${uriPath}`; } else if ( isWindows - && uri.path.charCodeAt(0) === CharCode.Slash - && (uri.path.charCodeAt(1) >= CharCode.A && uri.path.charCodeAt(1) <= CharCode.Z || uri.path.charCodeAt(1) >= CharCode.a && uri.path.charCodeAt(1) <= CharCode.z) - && uri.path.charCodeAt(2) === CharCode.Colon + && uriPath.charCodeAt(0) === CharCode.Slash + && extpath.isWindowsDriveLetter(uriPath.charCodeAt(1)) + && uriPath.charCodeAt(2) === CharCode.Colon ) { - value = uri.path.substr(1); + value = uriPath.substr(1); } else { // other path - value = uri.path; + value = uriPath; } if (isWindows) { value = value.replace(/\//g, '\\'); @@ -152,7 +170,95 @@ export function fsPath(uri: URI): string { * Returns true if the URI path is absolute. */ export function isAbsolutePath(resource: URI): boolean { - return paths.isAbsolute(resource.path); + return !!resource.path && resource.path[0] === '/'; +} + +/** + * Returns true if the URI path has a trailing path separator + */ +export function hasTrailingPathSeparator(resource: URI, sep: string = paths.sep): boolean { + if (resource.scheme === Schemas.file) { + const fsp = originalFSPath(resource); + return fsp.length > extpath.getRoot(fsp).length && fsp[fsp.length - 1] === sep; + } else { + const p = resource.path; + return p.length > 1 && p.charCodeAt(p.length - 1) === CharCode.Slash; // ignore the slash at offset 0 + } +} + +/** + * Removes a trailing path separator, if there's one. + * Important: Doesn't remove the first slash, it would make the URI invalid + */ +export function removeTrailingPathSeparator(resource: URI, sep: string = paths.sep): URI { + if (hasTrailingPathSeparator(resource, sep)) { + return resource.with({ path: resource.path.substr(0, resource.path.length - 1) }); + } + return resource; +} + +/** + * Adds a trailing path separator to the URI if there isn't one already. + * For example, c:\ would be unchanged, but c:\users would become c:\users\ + */ +export function addTrailingPathSeparator(resource: URI, sep: string = paths.sep): URI { + let isRootSep: boolean = false; + if (resource.scheme === Schemas.file) { + const fsp = originalFSPath(resource); + isRootSep = ((fsp !== undefined) && (fsp.length === extpath.getRoot(fsp).length) && (fsp[fsp.length - 1] === sep)); + } else { + sep = '/'; + const p = resource.path; + isRootSep = p.length === 1 && p.charCodeAt(p.length - 1) === CharCode.Slash; + } + if (!isRootSep && !hasTrailingPathSeparator(resource, sep)) { + return resource.with({ path: resource.path + '/' }); + } + return resource; +} + +/** + * Returns a relative path between two URIs. If the URIs don't have the same schema or authority, `undefined` is returned. + * The returned relative path always uses forward slashes. + */ +export function relativePath(from: URI, to: URI, ignoreCase = hasToIgnoreCase(from)): string | undefined { + if (from.scheme !== to.scheme || !isEqualAuthority(from.authority, to.authority)) { + return undefined; + } + if (from.scheme === Schemas.file) { + const relativePath = paths.relative(from.path, to.path); + return isWindows ? extpath.toSlashes(relativePath) : relativePath; + } + let fromPath = from.path || '/', toPath = to.path || '/'; + if (ignoreCase) { + // make casing of fromPath match toPath + let i = 0; + for (const len = Math.min(fromPath.length, toPath.length); i < len; i++) { + if (fromPath.charCodeAt(i) !== toPath.charCodeAt(i)) { + if (fromPath.charAt(i).toLowerCase() !== toPath.charAt(i).toLowerCase()) { + break; + } + } + } + fromPath = toPath.substr(0, i) + fromPath.substr(i); + } + return paths.posix.relative(fromPath, toPath); +} + +/** + * Resolves a absolute or relative path against a base URI. + */ +export function resolvePath(base: URI, path: string): URI { + if (base.scheme === Schemas.file) { + const newURI = URI.file(paths.resolve(originalFSPath(base), path)); + return base.with({ + authority: newURI.authority, + path: newURI.path + }); + } + return base.with({ + path: paths.posix.resolve(base.path, path) + }); } export function distinctParents(items: T[], resourceAccessor: (item: T) => URI): T[] { @@ -175,21 +281,6 @@ export function distinctParents(items: T[], resourceAccessor: (item: T) => UR return distinctParents; } -/** - * Tests whether the given URL is a file URI created by `URI.parse` instead of `URI.file`. - * Such URI have no scheme or scheme that consist of a single letter (windows drive letter) - * @param candidate The URI to test - * @returns A corrected, real file URI if the input seems to be malformed. - * Undefined is returned if the input URI looks fine. - */ -export function isMalformedFileUri(candidate: URI): URI | undefined { - if (!candidate.scheme || isWindows && candidate.scheme.match(/^[a-zA-Z]$/)) { - return URI.file((candidate.scheme ? candidate.scheme + ':' : '') + candidate.path); - } - return undefined; -} - - /** * Data URI related helpers. */ @@ -223,3 +314,43 @@ export namespace DataUri { return metadata; } } + +export class ResourceGlobMatcher { + + private readonly globalExpression: ParsedExpression; + private readonly expressionsByRoot: TernarySearchTree<{ root: URI, expression: ParsedExpression }> = TernarySearchTree.forPaths<{ root: URI, expression: ParsedExpression }>(); + + constructor( + globalExpression: IExpression, + rootExpressions: { root: URI, expression: IExpression }[] + ) { + this.globalExpression = parse(globalExpression); + for (const expression of rootExpressions) { + this.expressionsByRoot.set(expression.root.toString(), { root: expression.root, expression: parse(expression.expression) }); + } + } + + matches(resource: URI): boolean { + const rootExpression = this.expressionsByRoot.findSubstr(resource.toString()); + if (rootExpression) { + const path = relativePath(rootExpression.root, resource); + if (path && !!rootExpression.expression(path)) { + return true; + } + } + return !!this.globalExpression(resource.path); + } +} + +export function toLocalResource(resource: URI, authority: string | undefined): URI { + if (authority) { + let path = resource.path; + if (path && path[0] !== paths.posix.sep) { + path = paths.posix.sep + path; + } + + return resource.with({ scheme: Schemas.vscodeRemote, authority, path }); + } + + return resource.with({ scheme: Schemas.file }); +} \ No newline at end of file diff --git a/src/vs/base/common/scrollable.ts b/src/vs/base/common/scrollable.ts index f33897a9f3b..faee10bed56 100644 --- a/src/vs/base/common/scrollable.ts +++ b/src/vs/base/common/scrollable.ts @@ -117,13 +117,13 @@ export class ScrollState implements IScrollDimensions, IScrollPosition { } public createScrollEvent(previous: ScrollState): ScrollEvent { - let widthChanged = (this.width !== previous.width); - let scrollWidthChanged = (this.scrollWidth !== previous.scrollWidth); - let scrollLeftChanged = (this.scrollLeft !== previous.scrollLeft); + const widthChanged = (this.width !== previous.width); + const scrollWidthChanged = (this.scrollWidth !== previous.scrollWidth); + const scrollLeftChanged = (this.scrollLeft !== previous.scrollLeft); - let heightChanged = (this.height !== previous.height); - let scrollHeightChanged = (this.scrollHeight !== previous.scrollHeight); - let scrollTopChanged = (this.scrollTop !== previous.scrollTop); + const heightChanged = (this.height !== previous.height); + const scrollHeightChanged = (this.scrollHeight !== previous.scrollHeight); + const scrollTopChanged = (this.scrollTop !== previous.scrollTop); return { width: this.width, @@ -377,8 +377,8 @@ export class SmoothScrollingOperation { private readonly _startTime: number; public animationFrameDisposable: IDisposable | null; - private scrollLeft: IAnimation; - private scrollTop: IAnimation; + private scrollLeft!: IAnimation; + private scrollTop!: IAnimation; protected constructor(from: ISmoothScrollPosition, to: ISmoothScrollPosition, startTime: number, duration: number) { this.from = from; diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index e46f0ee3937..d4397d3279d 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -21,8 +21,8 @@ export function isFalsyOrWhitespace(str: string | undefined): boolean { * @returns the provided number with the given number of preceding zeros. */ export function pad(n: number, l: number, char: string = '0'): string { - let str = '' + n; - let r = [str]; + const str = '' + n; + const r = [str]; for (let i = str.length; i < l; i++) { r.push(char); @@ -44,7 +44,7 @@ export function format(value: string, ...args: any[]): string { return value; } return value.replace(_formatRegexp, function (match, group) { - let idx = parseInt(group, 10); + const idx = parseInt(group, 10); return isNaN(idx) || idx < 0 || idx >= args.length ? match : args[idx]; @@ -56,7 +56,7 @@ export function format(value: string, ...args: any[]): string { * being used e.g. in HTMLElement.innerHTML. */ export function escape(html: string): string { - return html.replace(/[<|>|&]/g, function (match) { + return html.replace(/[<>&]/g, function (match) { switch (match) { case '<': return '<'; case '>': return '>'; @@ -79,7 +79,7 @@ export function escapeRegExpCharacters(value: string): string { * @param needle the thing to trim (default is a blank) */ export function trim(haystack: string, needle: string = ' '): string { - let trimmed = ltrim(haystack, needle); + const trimmed = ltrim(haystack, needle); return rtrim(trimmed, needle); } @@ -93,7 +93,7 @@ export function ltrim(haystack: string, needle: string): string { return haystack; } - let needleLen = needle.length; + const needleLen = needle.length; if (needleLen === 0 || haystack.length === 0) { return haystack; } @@ -116,7 +116,7 @@ export function rtrim(haystack: string, needle: string): string { return haystack; } - let needleLen = needle.length, + const needleLen = needle.length, haystackLen = haystack.length; if (needleLen === 0 || haystackLen === 0) { @@ -173,7 +173,7 @@ export function startsWith(haystack: string, needle: string): boolean { * Determines if haystack ends with needle. */ export function endsWith(haystack: string, needle: string): boolean { - let diff = haystack.length - needle.length; + const diff = haystack.length - needle.length; if (diff > 0) { return haystack.indexOf(needle, diff) === diff; } else if (diff === 0) { @@ -232,8 +232,8 @@ export function regExpLeadsToEndlessLoop(regexp: RegExp): boolean { // We check against an empty string. If the regular expression doesn't advance // (e.g. ends in an endless loop) it will match an empty string. - let match = regexp.exec(''); - return !!(match && regexp.lastIndex === 0); + const match = regexp.exec(''); + return !!(match && regexp.lastIndex === 0); } export function regExpContainsBackreference(regexpValue: string): boolean { @@ -253,7 +253,7 @@ export function regExpFlags(regexp: RegExp): string { */ export function firstNonWhitespaceIndex(str: string): number { for (let i = 0, len = str.length; i < len; i++) { - let chCode = str.charCodeAt(i); + const chCode = str.charCodeAt(i); if (chCode !== CharCode.Space && chCode !== CharCode.Tab) { return i; } @@ -267,7 +267,7 @@ export function firstNonWhitespaceIndex(str: string): number { */ export function getLeadingWhitespace(str: string, start: number = 0, end: number = str.length): string { for (let i = start; i < end; i++) { - let chCode = str.charCodeAt(i); + const chCode = str.charCodeAt(i); if (chCode !== CharCode.Space && chCode !== CharCode.Tab) { return str.substring(start, i); } @@ -281,7 +281,7 @@ export function getLeadingWhitespace(str: string, start: number = 0, end: number */ export function lastNonWhitespaceIndex(str: string, startIndex: number = str.length - 1): number { for (let i = startIndex; i >= 0; i--) { - let chCode = str.charCodeAt(i); + const chCode = str.charCodeAt(i); if (chCode !== CharCode.Space && chCode !== CharCode.Tab) { return i; } @@ -380,7 +380,7 @@ function doEqualsIgnoreCase(a: string, b: string, stopAt = a.length): boolean { // a-z A-Z if (isAsciiLetter(codeA) && isAsciiLetter(codeB)) { - let diff = Math.abs(codeA - codeB); + const diff = Math.abs(codeA - codeB); if (diff !== 0 && diff !== 32) { return false; } @@ -431,8 +431,8 @@ export function commonSuffixLength(a: string, b: string): number { let i: number, len = Math.min(a.length, b.length); - let aLastIndex = a.length - 1; - let bLastIndex = b.length - 1; + const aLastIndex = a.length - 1; + const bLastIndex = b.length - 1; for (i = 0; i < len; i++) { if (a.charCodeAt(aLastIndex - i) !== b.charCodeAt(bLastIndex - i)) { @@ -459,7 +459,7 @@ function substrEquals(a: string, aStart: number, aEnd: number, b: string, bStart * For instance `overlap("foobar", "arr, I'm a pirate") === 2`. */ export function overlap(a: string, b: string): number { - let aEnd = a.length; + const aEnd = a.length; let bEnd = b.length; let aStart = aEnd - bEnd; @@ -486,9 +486,9 @@ export function overlap(a: string, b: string): number { // Code points U+0000 to U+D7FF and U+E000 to U+FFFF are represented on a single character // Code points U+10000 to U+10FFFF are represented on two consecutive characters //export function getUnicodePoint(str:string, index:number, len:number):number { -// let chrCode = str.charCodeAt(index); +// const chrCode = str.charCodeAt(index); // if (0xD800 <= chrCode && chrCode <= 0xDBFF && index + 1 < len) { -// let nextChrCode = str.charCodeAt(index + 1); +// const nextChrCode = str.charCodeAt(index + 1); // if (0xDC00 <= nextChrCode && nextChrCode <= 0xDFFF) { // return (chrCode - 0xD800) << 10 + (nextChrCode - 0xDC00) + 0x10000; // } @@ -627,6 +627,21 @@ export function removeAnsiEscapeCodes(str: string): string { return str; } +export const removeAccents: (str: string) => string = (function () { + if (typeof (String.prototype as any).normalize !== 'function') { + // ☹️ no ES6 features... + return function (str: string) { return str; }; + } else { + // transform into NFD form and remove accents + // see: https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript/37511463#37511463 + const regex = /[\u0300-\u036f]/g; + return function (str: string) { + return (str as any).normalize('NFD').replace(regex, empty); + }; + } +})(); + + // -- UTF-8 BOM export const UTF8_BOM_CHARACTER = String.fromCharCode(CharCode.UTF8_BOM); @@ -670,7 +685,7 @@ export function fuzzyContains(target: string, query: string): boolean { let index = 0; let lastIndexOf = -1; while (index < queryLen) { - let indexOf = targetLower.indexOf(query[index], lastIndexOf + 1); + const indexOf = targetLower.indexOf(query[index], lastIndexOf + 1); if (indexOf < 0) { return false; } diff --git a/src/vs/base/common/types.ts b/src/vs/base/common/types.ts index 447ba503496..56d365091e9 100644 --- a/src/vs/base/common/types.ts +++ b/src/vs/base/common/types.ts @@ -49,7 +49,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): boolean { +export function isObject(obj: any): 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. @@ -93,7 +93,6 @@ export function isUndefinedOrNull(obj: any): obj is undefined | null { return isUndefined(obj) || obj === null; } - const hasOwnProperty = Object.prototype.hasOwnProperty; /** @@ -124,7 +123,7 @@ export function isFunction(obj: any): obj is Function { * @returns whether the provided parameters is are JavaScript Function or not. */ export function areFunctions(...objects: any[]): boolean { - return objects && objects.length > 0 && objects.every(isFunction); + return objects.length > 0 && objects.every(isFunction); } export type TypeConstraint = string | Function; @@ -143,8 +142,12 @@ export function validateConstraint(arg: any, constraint: TypeConstraint | undefi throw new Error(`argument does not match constraint: typeof ${constraint}`); } } else if (isFunction(constraint)) { - if (arg instanceof constraint) { - return; + try { + if (arg instanceof constraint) { + return; + } + } catch{ + // ignore } if (!isUndefinedOrNull(arg) && arg.constructor === constraint) { return; @@ -156,13 +159,51 @@ export function validateConstraint(arg: any, constraint: TypeConstraint | undefi } } -/** - * Creates a new object of the provided class and will call the constructor with - * any additional argument supplied. - */ -export function create(ctor: Function, ...args: any[]): any { - let obj = Object.create(ctor.prototype); - ctor.apply(obj, args); - - return obj; +export function getAllPropertyNames(obj: object): string[] { + let res: string[] = []; + let proto = Object.getPrototypeOf(obj); + while (Object.prototype !== proto) { + res = res.concat(Object.getOwnPropertyNames(proto)); + proto = Object.getPrototypeOf(proto); + } + return res; +} + +export function getAllMethodNames(obj: object): string[] { + const methods: string[] = []; + for (const prop of getAllPropertyNames(obj)) { + if (typeof (obj as any)[prop] === 'function') { + methods.push(prop); + } + } + return methods; +} + +export function createProxyObject(methodNames: string[], invoke: (method: string, args: any[]) => any): T { + const createProxyMethod = (method: string): () => any => { + return function () { + const args = Array.prototype.slice.call(arguments, 0); + return invoke(method, args); + }; + }; + + let result = {} as T; + for (const methodName of methodNames) { + (result)[methodName] = createProxyMethod(methodName); + } + return result; +} + +/** + * Converts null to undefined, passes all other values through. + */ +export function withNullAsUndefined(x: T | null): T | undefined { + return x === null ? undefined : x; +} + +/** + * Converts undefined to null, passes all other values through. + */ +export function withUndefinedAsNull(x: T | undefined): T | null { + return typeof x === 'undefined' ? null : x; } diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index bd39facb709..966555e04d0 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -56,6 +56,21 @@ function _validateUri(ret: URI, _strict?: boolean): void { } } +// for a while we allowed uris *without* schemes and this is the migration +// for them, e.g. an uri without scheme and without strict-mode warns and falls +// back to the file-scheme. that should cause the least carnage and still be a +// clear warning +function _schemeFix(scheme: string, _strict: boolean): string { + if (_strict || _throwOnMissingSchema) { + return scheme || _empty; + } + if (!scheme) { + console.trace('BAD uri lacks scheme, falling back to file-scheme.'); + scheme = 'file'; + } + return scheme; +} + // implements a bit of https://tools.ietf.org/html/rfc3986#section-5 function _referenceResolution(scheme: string, path: string): string { @@ -108,7 +123,10 @@ export class URI implements UriComponents { && typeof (thing).fragment === 'string' && typeof (thing).path === 'string' && typeof (thing).query === 'string' - && typeof (thing).scheme === 'string'; + && typeof (thing).scheme === 'string' + && typeof (thing).fsPath === 'function' + && typeof (thing).with === 'function' + && typeof (thing).toString === 'function'; } /** @@ -151,7 +169,7 @@ export class URI implements UriComponents { /** * @internal */ - protected constructor(schemeOrData: string | UriComponents, authority?: string, path?: string, query?: string, fragment?: string, _strict?: boolean) { + protected constructor(schemeOrData: string | UriComponents, authority?: string, path?: string, query?: string, fragment?: string, _strict: boolean = false) { if (typeof schemeOrData === 'object') { this.scheme = schemeOrData.scheme || _empty; @@ -163,7 +181,7 @@ export class URI implements UriComponents { // that creates uri components. // _validateUri(this); } else { - this.scheme = schemeOrData || _empty; + this.scheme = _schemeFix(schemeOrData, _strict); this.authority = authority || _empty; this.path = _referenceResolution(this.scheme, path || _empty); this.query = query || _empty; @@ -208,7 +226,7 @@ export class URI implements UriComponents { // ---- modify to new ------------------------- - public with(change: { scheme?: string; authority?: string | null; path?: string | null; query?: string | null; fragment?: string | null }): URI { + with(change: { scheme?: string; authority?: string | null; path?: string | null; query?: string | null; fragment?: string | null }): URI { if (!change) { return this; @@ -261,7 +279,7 @@ export class URI implements UriComponents { * * @param value A string which represents an URI (see `URI#toString`). */ - public static parse(value: string, _strict: boolean = false): URI { + static parse(value: string, _strict: boolean = false): URI { const match = _regexp.exec(value); if (!match) { return new _URI(_empty, _empty, _empty, _empty, _empty); @@ -297,7 +315,7 @@ export class URI implements UriComponents { * * @param path A file system path (see `URI#fsPath`) */ - public static file(path: string): URI { + static file(path: string): URI { let authority = _empty; @@ -311,7 +329,7 @@ export class URI implements UriComponents { // check for authority as used in UNC shares // or use the path as given if (path[0] === _slash && path[1] === _slash) { - let idx = path.indexOf(_slash, 2); + const idx = path.indexOf(_slash, 2); if (idx === -1) { authority = path.substring(2); path = _slash; @@ -324,7 +342,7 @@ export class URI implements UriComponents { return new _URI('file', authority, path, _empty, _empty); } - public static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI { + static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI { return new _URI( components.scheme, components.authority, @@ -347,23 +365,27 @@ export class URI implements UriComponents { * * @param skipEncoding Do not encode the result, default is `false` */ - public toString(skipEncoding: boolean = false): string { + toString(skipEncoding: boolean = false): string { return _asFormatted(this, skipEncoding); } - public toJSON(): object { + toJSON(): UriComponents { return this; } - static revive(data: UriComponents | any): URI { + static revive(data: UriComponents | URI): URI; + static revive(data: UriComponents | URI | undefined): URI | undefined; + static revive(data: UriComponents | URI | null): URI | null; + static revive(data: UriComponents | URI | undefined | null): URI | undefined | null; + static revive(data: UriComponents | URI | undefined | null): URI | undefined | null { if (!data) { return data; } else if (data instanceof URI) { return data; } else { - let result = new _URI(data); - result._fsPath = (data).fsPath; + const result = new _URI(data); result._formatted = (data).external; + result._fsPath = (data)._sep === _pathSepMarker ? (data).fsPath : null; return result; } } @@ -379,10 +401,12 @@ export interface UriComponents { interface UriState extends UriComponents { $mid: number; - fsPath: string; external: string; + fsPath: string; + _sep: 1 | undefined; } +const _pathSepMarker = isWindows ? 1 : undefined; // tslint:disable-next-line:class-name class _URI extends URI { @@ -397,7 +421,7 @@ class _URI extends URI { return this._fsPath; } - public toString(skipEncoding: boolean = false): string { + toString(skipEncoding: boolean = false): string { if (!skipEncoding) { if (!this._formatted) { this._formatted = _asFormatted(this, false); @@ -409,13 +433,14 @@ class _URI extends URI { } } - toJSON(): object { + toJSON(): UriComponents { const res = { $mid: 1 }; // cached state if (this._fsPath) { res.fsPath = this._fsPath; + res._sep = _pathSepMarker; } if (this._formatted) { res.external = this._formatted; @@ -470,7 +495,7 @@ function encodeURIComponentFast(uriComponent: string, allowSlash: boolean): stri let nativeEncodePos = -1; for (let pos = 0; pos < uriComponent.length; pos++) { - let code = uriComponent.charCodeAt(pos); + const code = uriComponent.charCodeAt(pos); // unreserved characters: https://tools.ietf.org/html/rfc3986#section-2.3 if ( @@ -500,7 +525,7 @@ function encodeURIComponentFast(uriComponent: string, allowSlash: boolean): stri } // check with default table first - let escaped = encodeTable[code]; + const escaped = encodeTable[code]; if (escaped !== undefined) { // check if we are delaying native encode @@ -529,7 +554,7 @@ function encodeURIComponentFast(uriComponent: string, allowSlash: boolean): stri function encodeURIComponentMinimal(path: string): string { let res: string | undefined = undefined; for (let pos = 0; pos < path.length; pos++) { - let code = path.charCodeAt(pos); + const code = path.charCodeAt(pos); if (code === CharCode.Hash || code === CharCode.QuestionMark) { if (res === undefined) { res = path.substr(0, pos); @@ -619,12 +644,12 @@ function _asFormatted(uri: URI, skipEncoding: boolean): string { if (path) { // lower-case windows drive letters in /C:/fff or C:/fff if (path.length >= 3 && path.charCodeAt(0) === CharCode.Slash && path.charCodeAt(2) === CharCode.Colon) { - let code = path.charCodeAt(1); + const code = path.charCodeAt(1); if (code >= CharCode.A && code <= CharCode.Z) { path = `/${String.fromCharCode(code + 32)}:${path.substr(3)}`; // "/c:".length === 3 } } else if (path.length >= 2 && path.charCodeAt(1) === CharCode.Colon) { - let code = path.charCodeAt(0); + const code = path.charCodeAt(0); if (code >= CharCode.A && code <= CharCode.Z) { path = `${String.fromCharCode(code + 32)}:${path.substr(2)}`; // "/c:".length === 3 } diff --git a/src/vs/base/common/uriIpc.ts b/src/vs/base/common/uriIpc.ts index 374ffd99055..ef2291d49b1 100644 --- a/src/vs/base/common/uriIpc.ts +++ b/src/vs/base/common/uriIpc.ts @@ -4,11 +4,57 @@ *--------------------------------------------------------------------------------------------*/ import { URI, UriComponents } from 'vs/base/common/uri'; +import { MarshalledObject } from 'vs/base/common/marshalling'; export interface IURITransformer { transformIncoming(uri: UriComponents): UriComponents; - transformOutgoing(uri: URI): URI; transformOutgoing(uri: UriComponents): UriComponents; + transformOutgoingURI(uri: URI): URI; + transformOutgoingScheme(scheme: string): string; +} + +export interface UriParts { + scheme: string; + authority?: string; + path?: string; +} + +export interface IRawURITransformer { + transformIncoming(uri: UriParts): UriParts; + transformOutgoing(uri: UriParts): UriParts; + transformOutgoingScheme(scheme: string): string; +} + +function toJSON(uri: URI): UriComponents { + return uri.toJSON(); +} + +export class URITransformer implements IURITransformer { + + private readonly _uriTransformer: IRawURITransformer; + + constructor(uriTransformer: IRawURITransformer) { + this._uriTransformer = uriTransformer; + } + + public transformIncoming(uri: UriComponents): UriComponents { + const result = this._uriTransformer.transformIncoming(uri); + return (result === uri ? uri : toJSON(URI.from(result))); + } + + public transformOutgoing(uri: UriComponents): UriComponents { + const result = this._uriTransformer.transformOutgoing(uri); + return (result === uri ? uri : toJSON(URI.from(result))); + } + + public transformOutgoingURI(uri: URI): URI { + const result = this._uriTransformer.transformOutgoing(uri); + return (result === uri ? uri : URI.from(result)); + } + + public transformOutgoingScheme(scheme: string): string { + return this._uriTransformer.transformOutgoingScheme(scheme); + } } export const DefaultURITransformer: IURITransformer = new class { @@ -16,9 +62,94 @@ export const DefaultURITransformer: IURITransformer = new class { return uri; } - transformOutgoing(uri: URI): URI; - transformOutgoing(uri: UriComponents): UriComponents; - transformOutgoing(uri: URI | UriComponents): URI | UriComponents { + transformOutgoing(uri: UriComponents): UriComponents { return uri; } -}; \ No newline at end of file + + transformOutgoingURI(uri: URI): URI { + return uri; + } + + transformOutgoingScheme(scheme: string): string { + return scheme; + } +}; + +function _transformOutgoingURIs(obj: any, transformer: IURITransformer, depth: number): any { + + if (!obj || depth > 200) { + return null; + } + + if (typeof obj === 'object') { + if (obj instanceof URI) { + return transformer.transformOutgoing(obj); + } + + // walk object (or array) + for (let key in obj) { + if (Object.hasOwnProperty.call(obj, key)) { + const r = _transformOutgoingURIs(obj[key], transformer, depth + 1); + if (r !== null) { + obj[key] = r; + } + } + } + } + + return null; +} + +export function transformOutgoingURIs(obj: T, transformer: IURITransformer): T { + const result = _transformOutgoingURIs(obj, transformer, 0); + if (result === null) { + // no change + return obj; + } + return result; +} + + +function _transformIncomingURIs(obj: any, transformer: IURITransformer, revive: boolean, depth: number): any { + + if (!obj || depth > 200) { + return null; + } + + if (typeof obj === 'object') { + + if ((obj).$mid === 1) { + return revive ? URI.revive(transformer.transformIncoming(obj)) : transformer.transformIncoming(obj); + } + + // walk object (or array) + for (let key in obj) { + if (Object.hasOwnProperty.call(obj, key)) { + const r = _transformIncomingURIs(obj[key], transformer, revive, depth + 1); + if (r !== null) { + obj[key] = r; + } + } + } + } + + return null; +} + +export function transformIncomingURIs(obj: T, transformer: IURITransformer): T { + const result = _transformIncomingURIs(obj, transformer, false, 0); + if (result === null) { + // no change + return obj; + } + return result; +} + +export function transformAndReviveIncomingURIs(obj: T, transformer: IURITransformer): T { + const result = _transformIncomingURIs(obj, transformer, true, 0); + if (result === null) { + // no change + return obj; + } + return result; +} \ No newline at end of file diff --git a/src/vs/base/common/worker/simpleWorker.ts b/src/vs/base/common/worker/simpleWorker.ts index fc6db66a8e4..2cc1b188cac 100644 --- a/src/vs/base/common/worker/simpleWorker.ts +++ b/src/vs/base/common/worker/simpleWorker.ts @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ import { transformErrorForSerialization } from 'vs/base/common/errors'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { isWeb } from 'vs/base/common/platform'; +import * as types from 'vs/base/common/types'; const INITIALIZE = '$initialize'; -export interface IWorker { +export interface IWorker extends IDisposable { getId(): number; - postMessage(message: string): void; - dispose(): void; + postMessage(message: any, transfer: Transferable[]): void; } export interface IWorkerCallback { @@ -60,7 +60,7 @@ interface IMessageReply { } interface IMessageHandler { - sendMessage(msg: string): void; + sendMessage(msg: any, transfer?: ArrayBuffer[]): void; handleMessage(method: string, args: any[]): Promise; } @@ -98,14 +98,7 @@ class SimpleWorkerProtocol { }); } - public handleMessage(serializedMessage: string): void { - let message: IMessage; - try { - message = JSON.parse(serializedMessage); - } catch (e) { - // nothing - return; - } + public handleMessage(message: IMessage): void { if (!message || !message.vsWorker) { return; } @@ -167,30 +160,47 @@ class SimpleWorkerProtocol { } private _send(msg: IRequestMessage | IReplyMessage): void { - let strMsg = JSON.stringify(msg); - // console.log('SENDING: ' + strMsg); - this._handler.sendMessage(strMsg); + let transfer: ArrayBuffer[] = []; + if (msg.req) { + const m = msg; + for (let i = 0; i < m.args.length; i++) { + if (m.args[i] instanceof ArrayBuffer) { + transfer.push(m.args[i]); + } + } + } else { + const m = msg; + if (m.res instanceof ArrayBuffer) { + transfer.push(m.res); + } + } + this._handler.sendMessage(msg, transfer); } } +export interface IWorkerClient { + getProxyObject(): Promise; + dispose(): void; +} + /** * Main thread side */ -export class SimpleWorkerClient extends Disposable { +export class SimpleWorkerClient extends Disposable implements IWorkerClient { - private _worker: IWorker; - private _onModuleLoaded: Promise; - private _protocol: SimpleWorkerProtocol; - private _lazyProxy: Promise; + private readonly _worker: IWorker; + private readonly _onModuleLoaded: Promise; + private readonly _protocol: SimpleWorkerProtocol; + private readonly _lazyProxy: Promise; - constructor(workerFactory: IWorkerFactory, moduleId: string) { + constructor(workerFactory: IWorkerFactory, moduleId: string, host: H) { super(); let lazyProxyReject: ((err: any) => void) | null = null; this._worker = this._register(workerFactory.create( 'vs/base/common/worker/simpleWorker', - (msg: string) => { + (msg: any) => { this._protocol.handleMessage(msg); }, (err: any) => { @@ -203,12 +213,19 @@ export class SimpleWorkerClient extends Disposable { )); this._protocol = new SimpleWorkerProtocol({ - sendMessage: (msg: string): void => { - this._worker.postMessage(msg); + sendMessage: (msg: any, transfer: ArrayBuffer[]): void => { + this._worker.postMessage(msg, transfer); }, handleMessage: (method: string, args: any[]): Promise => { - // Intentionally not supporting worker -> main requests - return Promise.resolve(null); + if (typeof (host as any)[method] !== 'function') { + return Promise.reject(new Error('Missing method ' + method + ' on main thread host.')); + } + + try { + return Promise.resolve((host as any)[method].apply(host, args)); + } catch (e) { + return Promise.reject(e); + } } }); this._protocol.setWorkerId(this._worker.getId()); @@ -223,41 +240,33 @@ export class SimpleWorkerClient extends Disposable { loaderConfiguration = (self).requirejs.s.contexts._.config; } + const hostMethods = types.getAllMethodNames(host); + // Send initialize message this._onModuleLoaded = this._protocol.sendMessage(INITIALIZE, [ this._worker.getId(), + JSON.parse(JSON.stringify(loaderConfiguration)), moduleId, - loaderConfiguration + hostMethods, ]); - this._lazyProxy = new Promise((resolve, reject) => { - lazyProxyReject = reject; - this._onModuleLoaded.then((availableMethods: string[]) => { - let proxy = {}; - for (const methodName of availableMethods) { - (proxy as any)[methodName] = createProxyMethod(methodName, proxyMethodRequest); - } - resolve(proxy); - }, (e) => { - reject(e); - this._onError('Worker failed to load ' + moduleId, e); - }); - }); - // Create proxy to loaded code const proxyMethodRequest = (method: string, args: any[]): Promise => { return this._request(method, args); }; - const createProxyMethod = (method: string, proxyMethodRequest: (method: string, args: any[]) => Promise): () => Promise => { - return function () { - let args = Array.prototype.slice.call(arguments, 0); - return proxyMethodRequest(method, args); - }; - }; + this._lazyProxy = new Promise((resolve, reject) => { + lazyProxyReject = reject; + this._onModuleLoaded.then((availableMethods: string[]) => { + resolve(types.createProxyObject(availableMethods, proxyMethodRequest)); + }, (e) => { + reject(e); + this._onError('Worker failed to load ' + moduleId, e); + }); + }); } - public getProxyObject(): Promise { + public getProxyObject(): Promise { return this._lazyProxy; } @@ -280,31 +289,37 @@ export interface IRequestHandler { [prop: string]: any; } +export interface IRequestHandlerFactory { + (host: H): IRequestHandler; +} + /** * Worker side */ -export class SimpleWorkerServer { +export class SimpleWorkerServer { + private _requestHandlerFactory: IRequestHandlerFactory | null; private _requestHandler: IRequestHandler | null; private _protocol: SimpleWorkerProtocol; - constructor(postSerializedMessage: (msg: string) => void, requestHandler: IRequestHandler | null) { - this._requestHandler = requestHandler; + constructor(postMessage: (msg: any, transfer?: Transferable[]) => void, requestHandlerFactory: IRequestHandlerFactory | null) { + this._requestHandlerFactory = requestHandlerFactory; + this._requestHandler = null; this._protocol = new SimpleWorkerProtocol({ - sendMessage: (msg: string): void => { - postSerializedMessage(msg); + sendMessage: (msg: any, transfer: ArrayBuffer[]): void => { + postMessage(msg, transfer); }, handleMessage: (method: string, args: any[]): Promise => this._handleMessage(method, args) }); } - public onmessage(msg: string): void { + public onmessage(msg: any): void { this._protocol.handleMessage(msg); } private _handleMessage(method: string, args: any[]): Promise { if (method === INITIALIZE) { - return this.initialize(args[0], args[1], args[2]); + return this.initialize(args[0], args[1], args[2], args[3]); } if (!this._requestHandler || typeof this._requestHandler[method] !== 'function') { @@ -318,18 +333,19 @@ export class SimpleWorkerServer { } } - private initialize(workerId: number, moduleId: string, loaderConfig: any): Promise { + private initialize(workerId: number, loaderConfig: any, moduleId: string, hostMethods: string[]): Promise { this._protocol.setWorkerId(workerId); - if (this._requestHandler) { + const proxyMethodRequest = (method: string, args: any[]): Promise => { + return this._protocol.sendMessage(method, args); + }; + + const hostProxy = types.createProxyObject(hostMethods, proxyMethodRequest); + + if (this._requestHandlerFactory) { // static request handler - let methods: string[] = []; - for (let prop in this._requestHandler) { - if (typeof this._requestHandler[prop] === 'function') { - methods.push(prop); - } - } - return Promise.resolve(methods); + this._requestHandler = this._requestHandlerFactory(hostProxy); + return Promise.resolve(types.getAllMethodNames(this._requestHandler)); } if (loaderConfig) { @@ -350,23 +366,15 @@ export class SimpleWorkerServer { return new Promise((resolve, reject) => { // Use the global require to be sure to get the global config - (self).require([moduleId], (...result: any[]) => { - let handlerModule = result[0]; - this._requestHandler = handlerModule.create(); + (self).require([moduleId], (module: { create: IRequestHandlerFactory }) => { + this._requestHandler = module.create(hostProxy); if (!this._requestHandler) { reject(new Error(`No RequestHandler!`)); return; } - let methods: string[] = []; - for (let prop in this._requestHandler) { - if (typeof this._requestHandler[prop] === 'function') { - methods.push(prop); - } - } - - resolve(methods); + resolve(types.getAllMethodNames(this._requestHandler)); }, reject); }); } @@ -375,6 +383,6 @@ export class SimpleWorkerServer { /** * Called on the worker side */ -export function create(postMessage: (msg: string) => void): SimpleWorkerServer { +export function create(postMessage: (msg: string) => void): SimpleWorkerServer { return new SimpleWorkerServer(postMessage, null); } diff --git a/src/vs/base/node/config.ts b/src/vs/base/node/config.ts index 7b802137817..4e12fd565ea 100644 --- a/src/vs/base/node/config.ts +++ b/src/vs/base/node/config.ts @@ -4,13 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import * as fs from 'fs'; -import { dirname, basename } from 'path'; +import { dirname } from 'vs/base/common/path'; import * as objects from 'vs/base/common/objects'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { Disposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; import * as json from 'vs/base/common/json'; -import * as extfs from 'vs/base/node/extfs'; -import { isWindows } from 'vs/base/common/platform'; +import { statLink } from 'vs/base/node/pfs'; +import { realpath } from 'vs/base/node/extpath'; +import { watchFolder, watchFile } from 'vs/base/node/watcher'; export interface IConfigurationChangeEvent { config: T; @@ -40,36 +41,31 @@ export interface IConfigOptions { * - delayed processing of changes to accomodate for lots of changes * - configurable defaults */ -export class ConfigWatcher implements IConfigWatcher, IDisposable { +export class ConfigWatcher extends Disposable implements IConfigWatcher { private cache: T; private parseErrors: json.ParseError[]; private disposed: boolean; private loaded: boolean; private timeoutHandle: NodeJS.Timer | null; - private disposables: IDisposable[]; private readonly _onDidUpdateConfiguration: Emitter>; - private configName: string; constructor(private _path: string, private options: IConfigOptions = { defaultConfig: Object.create(null), onError: error => console.error(error) }) { - this.disposables = []; - this.configName = basename(this._path); - - this._onDidUpdateConfiguration = new Emitter>(); - this.disposables.push(this._onDidUpdateConfiguration); + super(); + this._onDidUpdateConfiguration = this._register(new Emitter>()); this.registerWatcher(); this.initAsync(); } - public get path(): string { + get path(): string { return this._path; } - public get hasParseErrors(): boolean { + get hasParseErrors(): boolean { return this.parseErrors && this.parseErrors.length > 0; } - public get onDidUpdateConfiguration(): Event> { + get onDidUpdateConfiguration(): Event> { return this._onDidUpdateConfiguration.event; } @@ -112,10 +108,10 @@ export class ConfigWatcher implements IConfigWatcher, IDisposable { try { this.parseErrors = []; res = this.options.parse ? this.options.parse(raw, this.parseErrors) : json.parse(raw, this.parseErrors); + return res || this.options.defaultConfig; } catch (error) { - // Ignore parsing errors - return this.options.defaultConfig; + return this.options.defaultConfig; // Ignore parsing errors } } @@ -126,50 +122,31 @@ export class ConfigWatcher implements IConfigWatcher, IDisposable { this.watch(parentFolder, true); // Check if the path is a symlink and watch its target if so - fs.lstat(this._path, (err, stat) => { - if (err || stat.isDirectory()) { - return; // path is not a valid file - } - - // We found a symlink - if (stat.isSymbolicLink()) { - fs.readlink(this._path, (err, realPath) => { - if (err) { - return; // path is not a valid symlink - } - - this.watch(realPath, false); - }); - } - }); + this.handleSymbolicLink().then(undefined, () => { /* ignore error */ }); } - private watch(path: string, isParentFolder: boolean): void { + private async handleSymbolicLink(): Promise { + const { stat, isSymbolicLink } = await statLink(this._path); + if (isSymbolicLink && !stat.isDirectory()) { + const realPath = await realpath(this._path); + + this.watch(realPath, false); + } + } + + private watch(path: string, isFolder: boolean): void { if (this.disposed) { return; // avoid watchers that will never get disposed by checking for being disposed } - this.disposables.push(extfs.watch(path, - (type, file) => this.onConfigFileChange(type, file, isParentFolder), - (error: string) => this.options.onError(error) - )); + if (isFolder) { + this._register(watchFolder(path, (type, path) => path === this._path ? this.onConfigFileChange() : undefined, error => this.options.onError(error))); + } else { + this._register(watchFile(path, () => this.onConfigFileChange(), error => this.options.onError(error))); + } } - private onConfigFileChange(eventType: string, filename: string | undefined, isParentFolder: boolean): void { - if (isParentFolder) { - - // Windows: in some cases the filename contains artifacts from the absolute path - // see https://github.com/nodejs/node/issues/19170 - // As such, we have to ensure that the filename basename is used for comparison. - if (isWindows && filename && filename !== this.configName) { - filename = basename(filename); - } - - if (filename !== this.configName) { - return; // a change to a sibling file that is not our config file - } - } - + private onConfigFileChange(): void { if (this.timeoutHandle) { global.clearTimeout(this.timeoutHandle); this.timeoutHandle = null; @@ -179,7 +156,7 @@ export class ConfigWatcher implements IConfigWatcher, IDisposable { this.timeoutHandle = global.setTimeout(() => this.reload(), this.options.changeBufferDelay || 0); } - public reload(callback?: (config: T) => void): void { + reload(callback?: (config: T) => void): void { this.loadAsync(currentConfig => { if (!objects.equals(currentConfig, this.cache)) { this.updateCache(currentConfig); @@ -193,7 +170,7 @@ export class ConfigWatcher implements IConfigWatcher, IDisposable { }); } - public getConfig(): T { + getConfig(): T { this.ensureLoaded(); return this.cache; @@ -205,8 +182,8 @@ export class ConfigWatcher implements IConfigWatcher, IDisposable { } } - public dispose(): void { + dispose(): void { this.disposed = true; - this.disposables = dispose(this.disposables); + super.dispose(); } } \ No newline at end of file diff --git a/src/vs/base/node/cpuUsage.sh b/src/vs/base/node/cpuUsage.sh index 94d56de9899..8e07feffaf7 100755 --- a/src/vs/base/node/cpuUsage.sh +++ b/src/vs/base/node/cpuUsage.sh @@ -30,7 +30,7 @@ for PID in "$@"; do fi PROCESS_BEFORE_TIMES[$ITER]=$PROCESS_TIME_BEFORE - ((ITER++)) + ((++ITER)) done # Wait for a second @@ -56,9 +56,9 @@ for PID in "$@"; do PROCESS_TIME_BEFORE=${PROCESS_BEFORE_TIMES[$ITER]} let PROCESS_DELTA=$PROCESS_TIME_AFTER-$PROCESS_TIME_BEFORE let TOTAL_DELTA=$TOTAL_TIME_AFTER-$TOTAL_TIME_BEFORE - CPU_USAGE=`echo "100*$PROCESS_DELTA/$TOTAL_DELTA" | bc -l` + CPU_USAGE=`echo "$((100*$PROCESS_DELTA/$TOTAL_DELTA))"` # Parent script reads from stdout, so echo result to be read echo $CPU_USAGE - ((ITER++)) + ((++ITER)) done diff --git a/src/vs/base/node/decoder.ts b/src/vs/base/node/decoder.ts index 5ef4abf19f7..5146d0e24de 100644 --- a/src/vs/base/node/decoder.ts +++ b/src/vs/base/node/decoder.ts @@ -23,9 +23,9 @@ export class LineDecoder { this.remaining = null; } - public write(buffer: Buffer): string[] { - let result: string[] = []; - let value = this.remaining + write(buffer: Buffer): string[] { + const result: string[] = []; + const value = this.remaining ? this.remaining + this.stringDecoder.write(buffer) : this.stringDecoder.write(buffer); @@ -41,7 +41,7 @@ export class LineDecoder { result.push(value.substring(start, idx)); idx++; if (idx < value.length) { - let lastChar = ch; + const lastChar = ch; ch = value.charCodeAt(idx); if ((lastChar === CharCode.CarriageReturn && ch === CharCode.LineFeed) || (lastChar === CharCode.LineFeed && ch === CharCode.CarriageReturn)) { idx++; @@ -56,7 +56,7 @@ export class LineDecoder { return result; } - public end(): string | null { + end(): string | null { return this.remaining; } } \ No newline at end of file diff --git a/src/vs/base/node/encoding.ts b/src/vs/base/node/encoding.ts index 069997e72b7..d89114aa099 100644 --- a/src/vs/base/node/encoding.ts +++ b/src/vs/base/node/encoding.ts @@ -3,122 +3,138 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as stream from 'vs/base/node/stream'; import * as iconv from 'iconv-lite'; import { isLinux, isMacintosh } from 'vs/base/common/platform'; import { exec } from 'child_process'; -import { Readable, Writable, WritableOptions } from 'stream'; +import { Readable, Writable } from 'stream'; +import { VSBuffer } from 'vs/base/common/buffer'; export const UTF8 = 'utf8'; export const UTF8_with_bom = 'utf8bom'; export const UTF16be = 'utf16be'; export const UTF16le = 'utf16le'; -export interface IDecodeStreamOptions { - guessEncoding?: boolean; - minBytesRequiredForDetection?: number; - overwriteEncoding?(detectedEncoding: string | null): string; +export type UTF_ENCODING = typeof UTF8 | typeof UTF8_with_bom | typeof UTF16be | typeof UTF16le; + +export function isUTFEncoding(encoding: string): encoding is UTF_ENCODING { + return [UTF8, UTF8_with_bom, UTF16be, UTF16le].some(utfEncoding => utfEncoding === encoding); } -export function toDecodeStream(readable: Readable, options: IDecodeStreamOptions): Promise<{ detected: IDetectedEncodingResult, stream: NodeJS.ReadableStream }> { +export const UTF16be_BOM = [0xFE, 0xFF]; +export const UTF16le_BOM = [0xFF, 0xFE]; +export const UTF8_BOM = [0xEF, 0xBB, 0xBF]; + +const ZERO_BYTE_DETECTION_BUFFER_MAX_LEN = 512; // number of bytes to look at to decide about a file being binary or not +const NO_GUESS_BUFFER_MAX_LEN = 512; // when not auto guessing the encoding, small number of bytes are enough +const AUTO_GUESS_BUFFER_MAX_LEN = 512 * 8; // with auto guessing we want a lot more content to be read for guessing + +export interface IDecodeStreamOptions { + guessEncoding: boolean; + minBytesRequiredForDetection?: number; + + overwriteEncoding(detectedEncoding: string | null): string; +} + +export interface IDecodeStreamResult { + stream: NodeJS.ReadableStream; + detected: IDetectedEncodingResult; +} + +export function toDecodeStream(readable: Readable, options: IDecodeStreamOptions): Promise { if (!options.minBytesRequiredForDetection) { options.minBytesRequiredForDetection = options.guessEncoding ? AUTO_GUESS_BUFFER_MAX_LEN : NO_GUESS_BUFFER_MAX_LEN; } - if (!options.overwriteEncoding) { - options.overwriteEncoding = detected => detected || UTF8; - } + return new Promise((resolve, reject) => { + const writer = new class extends Writable { + private decodeStream: NodeJS.ReadWriteStream; + private decodeStreamPromise: Promise; - return new Promise<{ detected: IDetectedEncodingResult, stream: NodeJS.ReadableStream }>((resolve, reject) => { + private bufferedChunks: Buffer[] = []; + private bytesBuffered = 0; - readable.on('error', reject); - - readable.pipe(new class extends Writable { - - private _decodeStream: NodeJS.ReadWriteStream; - private _decodeStreamConstruction: Promise; - private _buffer: Buffer[] = []; - private _bytesBuffered = 0; - - constructor(opts?: WritableOptions) { - super(opts); - this.once('finish', () => this._finish()); - } - - _write(chunk: any, encoding: string, callback: Function): void { + _write(chunk: Buffer, encoding: string, callback: (error: Error | null) => void): void { if (!Buffer.isBuffer(chunk)) { - callback(new Error('data must be a buffer')); + return callback(new Error('toDecodeStream(): data must be a buffer')); } - if (this._decodeStream) { - // just a forwarder now - this._decodeStream.write(chunk, callback); + // if the decode stream is ready, we just write directly + if (this.decodeStream) { + this.decodeStream.write(chunk, callback); + return; } - this._buffer.push(chunk); - this._bytesBuffered += chunk.length; + // otherwise we need to buffer the data until the stream is ready + this.bufferedChunks.push(chunk); + this.bytesBuffered += chunk.byteLength; - if (this._decodeStreamConstruction) { - // waiting for the decoder to be ready - this._decodeStreamConstruction.then(_ => callback(), err => callback(err)); + // waiting for the decoder to be ready + if (this.decodeStreamPromise) { + this.decodeStreamPromise.then(() => callback(null), error => callback(error)); + } - } else if (typeof options.minBytesRequiredForDetection === 'number' && this._bytesBuffered >= options.minBytesRequiredForDetection) { - // buffered enough data, create stream and forward data + // buffered enough data for encoding detection, create stream and forward data + else if (typeof options.minBytesRequiredForDetection === 'number' && this.bytesBuffered >= options.minBytesRequiredForDetection) { this._startDecodeStream(callback); + } - } else { - // only buffering - callback(); + // only buffering until enough data for encoding detection is there + else { + callback(null); } } - _startDecodeStream(callback: Function): void { + _startDecodeStream(callback: (error: Error | null) => void): void { - this._decodeStreamConstruction = Promise.resolve(detectEncodingFromBuffer({ - buffer: Buffer.concat(this._buffer), bytesRead: this._bytesBuffered + // detect encoding from buffer + this.decodeStreamPromise = Promise.resolve(detectEncodingFromBuffer({ + buffer: Buffer.concat(this.bufferedChunks), + bytesRead: this.bytesBuffered }, options.guessEncoding)).then(detected => { - if (options.overwriteEncoding) { - detected.encoding = options.overwriteEncoding(detected.encoding); - } - this._decodeStream = decodeStream(detected.encoding); - for (const buffer of this._buffer) { - this._decodeStream.write(buffer); - } - callback(); - resolve({ detected, stream: this._decodeStream }); - }, err => { - this.emit('error', err); - callback(err); + // ensure to respect overwrite of encoding + detected.encoding = options.overwriteEncoding(detected.encoding); + + // decode and write buffer + this.decodeStream = decodeStream(detected.encoding); + this.decodeStream.write(Buffer.concat(this.bufferedChunks), callback); + this.bufferedChunks.length = 0; + + // signal to the outside our detected encoding + // and final decoder stream + resolve({ detected, stream: this.decodeStream }); + }, error => { + this.emit('error', error); + + callback(error); }); } - _finish(): void { - if (this._decodeStream) { - // normal finish - this._decodeStream.end(); - } else { - // we were still waiting for data... - this._startDecodeStream(() => this._decodeStream.end()); + _final(callback: (error: Error | null) => void) { + + // normal finish + if (this.decodeStream) { + this.decodeStream.end(callback); + } + + // we were still waiting for data to do the encoding + // detection. thus, wrap up starting the stream even + // without all the data to get things going + else { + this._startDecodeStream(() => this.decodeStream.end(callback)); } } - }); + }; + + // errors + readable.on('error', reject); + + // pipe through + readable.pipe(writer); }); } -export function bomLength(encoding: string): number { - switch (encoding) { - case UTF8: - return 3; - case UTF16be: - case UTF16le: - return 2; - } - - return 0; -} - export function decode(buffer: Buffer, encoding: string): string { return iconv.decode(buffer, toNodeEncoding(encoding)); } @@ -131,7 +147,7 @@ export function encodingExists(encoding: string): boolean { return iconv.encodingExists(toNodeEncoding(encoding)); } -export function decodeStream(encoding: string | null): NodeJS.ReadWriteStream { +function decodeStream(encoding: string | null): NodeJS.ReadWriteStream { return iconv.decodeStream(toNodeEncoding(encoding)); } @@ -147,8 +163,8 @@ function toNodeEncoding(enc: string | null): string { return enc; } -export function detectEncodingByBOMFromBuffer(buffer: Buffer | null, bytesRead: number): string | null { - if (!buffer || bytesRead < 2) { +export function detectEncodingByBOMFromBuffer(buffer: Buffer | VSBuffer | null, bytesRead: number): string | null { + if (!buffer || bytesRead < UTF16be_BOM.length) { return null; } @@ -156,62 +172,54 @@ export function detectEncodingByBOMFromBuffer(buffer: Buffer | null, bytesRead: const b1 = buffer.readUInt8(1); // UTF-16 BE - if (b0 === 0xFE && b1 === 0xFF) { + if (b0 === UTF16be_BOM[0] && b1 === UTF16be_BOM[1]) { return UTF16be; } // UTF-16 LE - if (b0 === 0xFF && b1 === 0xFE) { + if (b0 === UTF16le_BOM[0] && b1 === UTF16le_BOM[1]) { return UTF16le; } - if (bytesRead < 3) { + if (bytesRead < UTF8_BOM.length) { return null; } const b2 = buffer.readUInt8(2); // UTF-8 - if (b0 === 0xEF && b1 === 0xBB && b2 === 0xBF) { + if (b0 === UTF8_BOM[0] && b1 === UTF8_BOM[1] && b2 === UTF8_BOM[2]) { return UTF8; } return null; } -/** - * Detects the Byte Order Mark in a given file. - * If no BOM is detected, null will be passed to callback. - */ -export function detectEncodingByBOM(file: string): Promise { - return stream.readExactlyByFile(file, 3).then(({ buffer, bytesRead }) => detectEncodingByBOMFromBuffer(buffer, bytesRead)); -} - const MINIMUM_THRESHOLD = 0.2; const IGNORE_ENCODINGS = ['ascii', 'utf-8', 'utf-16', 'utf-32']; /** * Guesses the encoding from buffer. */ -export function guessEncodingByBuffer(buffer: Buffer): Promise { - return import('jschardet').then(jschardet => { - jschardet.Constants.MINIMUM_THRESHOLD = MINIMUM_THRESHOLD; +async function guessEncodingByBuffer(buffer: Buffer): Promise { + const jschardet = await import('jschardet'); - const guessed = jschardet.detect(buffer); - if (!guessed || !guessed.encoding) { - return null; - } + jschardet.Constants.MINIMUM_THRESHOLD = MINIMUM_THRESHOLD; - const enc = guessed.encoding.toLowerCase(); + const guessed = jschardet.detect(buffer); + if (!guessed || !guessed.encoding) { + return null; + } - // Ignore encodings that cannot guess correctly - // (http://chardet.readthedocs.io/en/latest/supported-encodings.html) - if (0 <= IGNORE_ENCODINGS.indexOf(enc)) { - return null; - } + const enc = guessed.encoding.toLowerCase(); - return toIconvLiteEncoding(guessed.encoding); - }); + // Ignore encodings that cannot guess correctly + // (http://chardet.readthedocs.io/en/latest/supported-encodings.html) + if (0 <= IGNORE_ENCODINGS.indexOf(enc)) { + return null; + } + + return toIconvLiteEncoding(guessed.encoding); } const JSCHARDET_TO_ICONV_ENCODINGS: { [name: string]: string } = { @@ -263,18 +271,19 @@ export function toCanonicalName(enc: string): string { } } -const ZERO_BYTE_DETECTION_BUFFER_MAX_LEN = 512; // number of bytes to look at to decide about a file being binary or not -const NO_GUESS_BUFFER_MAX_LEN = 512; // when not auto guessing the encoding, small number of bytes are enough -const AUTO_GUESS_BUFFER_MAX_LEN = 512 * 8; // with auto guessing we want a lot more content to be read for guessing - export interface IDetectedEncodingResult { encoding: string | null; seemsBinary: boolean; } -export function detectEncodingFromBuffer(readResult: stream.ReadResult, autoGuessEncoding?: false): IDetectedEncodingResult; -export function detectEncodingFromBuffer(readResult: stream.ReadResult, autoGuessEncoding?: boolean): Promise; -export function detectEncodingFromBuffer({ buffer, bytesRead }: stream.ReadResult, autoGuessEncoding?: boolean): Promise | IDetectedEncodingResult { +export interface IReadResult { + buffer: Buffer | null; + bytesRead: number; +} + +export function detectEncodingFromBuffer(readResult: IReadResult, autoGuessEncoding?: false): IDetectedEncodingResult; +export function detectEncodingFromBuffer(readResult: IReadResult, autoGuessEncoding?: boolean): Promise; +export function detectEncodingFromBuffer({ buffer, bytesRead }: IReadResult, autoGuessEncoding?: boolean): Promise | IDetectedEncodingResult { // Always first check for BOM to find out about encoding let encoding = detectEncodingByBOMFromBuffer(buffer, bytesRead); @@ -359,7 +368,7 @@ const windowsTerminalEncodings = { '1252': 'cp1252' // West European Latin }; -export function resolveTerminalEncoding(verbose?: boolean): Promise { +export async function resolveTerminalEncoding(verbose?: boolean): Promise { let rawEncodingPromise: Promise; // Support a global environment variable to win over other mechanics @@ -392,7 +401,7 @@ export function resolveTerminalEncoding(verbose?: boolean): Promise { exec('chcp', (err, stdout, stderr) => { if (stdout) { - const windowsTerminalEncodingKeys = Object.keys(windowsTerminalEncodings); + const windowsTerminalEncodingKeys = Object.keys(windowsTerminalEncodings) as Array; for (const key of windowsTerminalEncodingKeys) { if (stdout.indexOf(key) >= 0) { return resolve(windowsTerminalEncodings[key]); @@ -405,24 +414,23 @@ export function resolveTerminalEncoding(verbose?: boolean): Promise { }); } - return rawEncodingPromise.then(rawEncoding => { - if (verbose) { - console.log(`Detected raw terminal encoding: ${rawEncoding}`); - } - - if (!rawEncoding || rawEncoding.toLowerCase() === 'utf-8' || rawEncoding.toLowerCase() === UTF8) { - return UTF8; - } - - const iconvEncoding = toIconvLiteEncoding(rawEncoding); - if (iconv.encodingExists(iconvEncoding)) { - return iconvEncoding; - } - - if (verbose) { - console.log('Unsupported terminal encoding, falling back to UTF-8.'); - } + const rawEncoding = await rawEncodingPromise; + if (verbose) { + console.log(`Detected raw terminal encoding: ${rawEncoding}`); + } + if (!rawEncoding || rawEncoding.toLowerCase() === 'utf-8' || rawEncoding.toLowerCase() === UTF8) { return UTF8; - }); + } + + const iconvEncoding = toIconvLiteEncoding(rawEncoding); + if (iconv.encodingExists(iconvEncoding)) { + return iconvEncoding; + } + + if (verbose) { + console.log('Unsupported terminal encoding, falling back to UTF-8.'); + } + + return UTF8; } diff --git a/src/vs/base/node/extfs.ts b/src/vs/base/node/extfs.ts deleted file mode 100644 index 08d2beab731..00000000000 --- a/src/vs/base/node/extfs.ts +++ /dev/null @@ -1,708 +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 * as fs from 'fs'; -import * as paths from 'path'; -import { nfcall } from 'vs/base/common/async'; -import { normalizeNFC } from 'vs/base/common/normalization'; -import * as platform from 'vs/base/common/platform'; -import * as strings from 'vs/base/common/strings'; -import * as uuid from 'vs/base/common/uuid'; -import { encode, encodeStream } from 'vs/base/node/encoding'; -import * as flow from 'vs/base/node/flow'; -import { CancellationToken } from 'vs/base/common/cancellation'; -import { IDisposable, toDisposable, Disposable } from 'vs/base/common/lifecycle'; - -const loop = flow.loop; - -export function readdirSync(path: string): string[] { - // Mac: uses NFD unicode form on disk, but we want NFC - // See also https://github.com/nodejs/node/issues/2165 - if (platform.isMacintosh) { - return fs.readdirSync(path).map(c => normalizeNFC(c)); - } - - return fs.readdirSync(path); -} - -export function readdir(path: string, callback: (error: Error | null, files: string[]) => void): void { - // Mac: uses NFD unicode form on disk, but we want NFC - // See also https://github.com/nodejs/node/issues/2165 - if (platform.isMacintosh) { - return fs.readdir(path, (error, children) => { - if (error) { - return callback(error, []); - } - - return callback(null, children.map(c => normalizeNFC(c))); - }); - } - - return fs.readdir(path, callback); -} - -export interface IStatAndLink { - stat: fs.Stats; - isSymbolicLink: boolean; -} - -export function statLink(path: string, callback: (error: Error | null, statAndIsLink: IStatAndLink | null) => void): void { - fs.lstat(path, (error, lstat) => { - if (error || lstat.isSymbolicLink()) { - fs.stat(path, (error, stat) => { - if (error) { - return callback(error, null); - } - - callback(null, { stat, isSymbolicLink: lstat && lstat.isSymbolicLink() }); - }); - } else { - callback(null, { stat: lstat, isSymbolicLink: false }); - } - }); -} - -export function copy(source: string, target: string, callback: (error: Error | null) => void, copiedSourcesIn?: { [path: string]: boolean }): void { - const copiedSources = copiedSourcesIn ? copiedSourcesIn : Object.create(null); - - fs.stat(source, (error, stat) => { - if (error) { - return callback(error); - } - - if (!stat.isDirectory()) { - return doCopyFile(source, target, stat.mode & 511, callback); - } - - if (copiedSources[source]) { - return callback(null); // escape when there are cycles (can happen with symlinks) - } - - copiedSources[source] = true; // remember as copied - - const proceed = function () { - readdir(source, (err, files) => { - loop(files, (file: string, clb: (error: Error | null, result: string[]) => void) => { - copy(paths.join(source, file), paths.join(target, file), (error: Error) => clb(error, []), copiedSources); - }, callback); - }); - }; - - mkdirp(target, stat.mode & 511).then(proceed, proceed); - }); -} - -function doCopyFile(source: string, target: string, mode: number, callback: (error: Error) => void): void { - const reader = fs.createReadStream(source); - const writer = fs.createWriteStream(target, { mode }); - - let finished = false; - const finish = (error?: Error) => { - if (!finished) { - finished = true; - - // in error cases, pass to callback - if (error) { - callback(error); - } - - // we need to explicitly chmod because of https://github.com/nodejs/node/issues/1104 - else { - fs.chmod(target, mode, callback); - } - } - }; - - // 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); -} - -export function mkdirp(path: string, mode?: number, token?: CancellationToken): Promise { - const mkdir = (): Promise => { - return nfcall(fs.mkdir, path, mode).then(undefined, (mkdirErr: NodeJS.ErrnoException) => { - - // ENOENT: a parent folder does not exist yet - if (mkdirErr.code === 'ENOENT') { - return Promise.reject(mkdirErr); - } - - // Any other error: check if folder exists and - // return normally in that case if its a folder - return nfcall(fs.stat, path).then((stat: fs.Stats) => { - if (!stat.isDirectory()) { - return Promise.reject(new Error(`'${path}' exists and is not a directory.`)); - } - - return null; - }, statErr => { - return Promise.reject(mkdirErr); // bubble up original mkdir error - }); - }); - }; - - // stop at root - if (path === paths.dirname(path)) { - return Promise.resolve(true); - } - - // recursively mkdir - return mkdir().then(undefined, (err: NodeJS.ErrnoException) => { - - // Respect cancellation - if (token && token.isCancellationRequested) { - return Promise.resolve(false); - } - - // ENOENT: a parent folder does not exist yet, continue - // to create the parent folder and then try again. - if (err.code === 'ENOENT') { - return mkdirp(paths.dirname(path), mode).then(mkdir); - } - - // Any other error - return Promise.reject(err); - }); -} - -// Deletes the given path by first moving it out of the workspace. This has two benefits. For one, the operation can return fast because -// after the rename, the contents are out of the workspace although not yet deleted. The greater benefit however is that this operation -// will fail in case any file is used by another process. fs.unlink() in node will not bail if a file unlinked is used by another process. -// However, the consequences are bad as outlined in all the related bugs from https://github.com/joyent/node/issues/7164 -export function del(path: string, tmpFolder: string, callback: (error: Error | null) => void, done?: (error: Error | null) => void): void { - fs.exists(path, exists => { - if (!exists) { - return callback(null); - } - - fs.stat(path, (err, stat) => { - if (err || !stat) { - return callback(err); - } - - // Special windows workaround: A file or folder that ends with a "." cannot be moved to another place - // because it is not a valid file name. In this case, we really have to do the deletion without prior move. - if (path[path.length - 1] === '.' || strings.endsWith(path, './') || strings.endsWith(path, '.\\')) { - return rmRecursive(path, callback); - } - - const pathInTemp = paths.join(tmpFolder, uuid.generateUuid()); - fs.rename(path, pathInTemp, (error: Error | null) => { - if (error) { - return rmRecursive(path, callback); // if rename fails, delete without tmp dir - } - - // Return early since the move succeeded - callback(null); - - // do the heavy deletion outside the callers callback - rmRecursive(pathInTemp, error => { - if (error) { - console.error(error); - } - - if (done) { - done(error); - } - }); - }); - }); - }); -} - -function rmRecursive(path: string, callback: (error: Error | null) => void): void { - if (path === '\\' || path === '/') { - return callback(new Error('Will not delete root!')); - } - - fs.exists(path, exists => { - if (!exists) { - callback(null); - } else { - fs.lstat(path, (err, stat) => { - if (err || !stat) { - callback(err); - } else if (!stat.isDirectory() || stat.isSymbolicLink() /* !!! never recurse into links when deleting !!! */) { - const mode = stat.mode; - if (!(mode & 128)) { // 128 === 0200 - fs.chmod(path, mode | 128, (err: Error) => { // 128 === 0200 - if (err) { - callback(err); - } else { - fs.unlink(path, callback); - } - }); - } else { - fs.unlink(path, callback); - } - } else { - readdir(path, (err, children) => { - if (err || !children) { - callback(err); - } else if (children.length === 0) { - fs.rmdir(path, callback); - } else { - let firstError: Error | null = null; - let childrenLeft = children.length; - children.forEach(child => { - rmRecursive(paths.join(path, child), (err: Error) => { - childrenLeft--; - if (err) { - firstError = firstError || err; - } - - if (childrenLeft === 0) { - if (firstError) { - callback(firstError); - } else { - fs.rmdir(path, callback); - } - } - }); - }); - } - }); - } - }); - } - }); -} - -export function delSync(path: string): void { - try { - const stat = fs.lstatSync(path); - if (stat.isDirectory() && !stat.isSymbolicLink()) { - readdirSync(path).forEach(child => delSync(paths.join(path, child))); - fs.rmdirSync(path); - } else { - fs.unlinkSync(path); - } - } catch (err) { - if (err.code === 'ENOENT') { - return; // not found - } - - throw err; - } -} - -export function mv(source: string, target: string, callback: (error: Error | null) => void): void { - if (source === target) { - return callback(null); - } - - function updateMtime(err: Error | null): void { - if (err) { - return callback(err); - } - - fs.stat(target, (error, stat) => { - if (error) { - return callback(error); - } - - if (stat.isDirectory()) { - return callback(null); - } - - fs.open(target, 'a', null, (err: Error, fd: number) => { - if (err) { - return callback(err); - } - - fs.futimes(fd, stat.atime, new Date(), (err: Error) => { - if (err) { - return callback(err); - } - - fs.close(fd, callback); - }); - }); - }); - } - - // Try native rename() - fs.rename(source, target, (err: Error) => { - if (!err) { - return updateMtime(null); - } - - // In two cases we fallback to classic copy and delete: - // - // 1.) The EXDEV error indicates that source and target are on different devices - // In this case, fallback to using a copy() operation as there is no way to - // rename() between different devices. - // - // 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 (err && source.toLowerCase() !== target.toLowerCase() && ((err).code === 'EXDEV') || strings.endsWith(source, '.')) { - return copy(source, target, (err: Error) => { - if (err) { - return callback(err); - } - - rmRecursive(source, updateMtime); - }); - } - - return callback(err); - }); -} - -export interface IWriteFileOptions { - mode?: number; - flag?: string; - encoding?: { - charset: string; - addBOM: boolean; - }; -} - -let canFlush = true; -export function writeFileAndFlush(path: string, data: string | Buffer | NodeJS.ReadableStream, options: IWriteFileOptions, callback: (error?: Error) => void): void { - options = ensureOptions(options); - - if (typeof data === 'string' || Buffer.isBuffer(data)) { - doWriteFileAndFlush(path, data, options, callback); - } else { - doWriteFileStreamAndFlush(path, data, options, callback); - } -} - -function doWriteFileStreamAndFlush(path: string, reader: NodeJS.ReadableStream, options: IWriteFileOptions, callback: (error?: Error) => void): void { - - // finish only once - let finished = false; - const finish = (error?: Error) => { - if (!finished) { - finished = true; - - // in error cases we need to manually close streams - // if the write stream was successfully opened - if (error) { - if (isOpen) { - writer.once('close', () => callback(error)); - writer.destroy(); - } else { - callback(error); - } - } - - // otherwise just return without error - else { - callback(); - } - } - }; - - // create writer to target. we set autoClose: false because we want to use the streams - // file descriptor to call fs.fdatasync to ensure the data is flushed to disk - const writer = fs.createWriteStream(path, { mode: options.mode, flags: options.flag, autoClose: false }); - - // Event: 'open' - // Purpose: save the fd for later use and start piping - // Notes: will not be called when there is an error opening the file descriptor! - let fd: number; - let isOpen: boolean; - writer.once('open', descriptor => { - fd = descriptor; - isOpen = true; - - // if an encoding is provided, we need to pipe the stream through - // an encoder stream and forward the encoding related options - if (options.encoding) { - reader = reader.pipe(encodeStream(options.encoding.charset, { addBOM: options.encoding.addBOM })); - } - - // start data piping only when we got a successful open. this ensures that we do - // not consume the stream when an error happens and helps to fix this issue: - // https://github.com/Microsoft/vscode/issues/42542 - reader.pipe(writer); - }); - - // Event: 'error' - // Purpose: to return the error to the outside and to close the write stream (does not happen automatically) - reader.once('error', error => finish(error)); - writer.once('error', error => finish(error)); - - // Event: 'finish' - // Purpose: use fs.fdatasync to flush the contents to disk - // Notes: event is called when the writer has finished writing to the underlying resource. we must call writer.close() - // because we have created the WriteStream with autoClose: false - writer.once('finish', () => { - - // flush to disk - if (canFlush && isOpen) { - fs.fdatasync(fd, (syncError: Error) => { - - // In some exotic setups it is well possible that node fails to sync - // In that case we disable flushing and warn to the console - if (syncError) { - console.warn('[node.js fs] fdatasync is now disabled for this session because it failed: ', syncError); - canFlush = false; - } - - writer.destroy(); - }); - } else { - writer.destroy(); - } - }); - - // Event: 'close' - // Purpose: signal we are done to the outside - // Notes: event is called when the writer's filedescriptor is closed - writer.once('close', () => finish()); -} - -// Calls fs.writeFile() followed by a fs.sync() call to flush the changes to disk -// We do this in cases where we want to make sure the data is really on disk and -// not in some cache. -// -// See https://github.com/nodejs/node/blob/v5.10.0/lib/fs.js#L1194 -function doWriteFileAndFlush(path: string, data: string | Buffer, options: IWriteFileOptions, callback: (error?: Error) => void): void { - if (options.encoding) { - data = encode(data, options.encoding.charset, { addBOM: options.encoding.addBOM }); - } - - if (!canFlush) { - return fs.writeFile(path, data, { mode: options.mode, flag: options.flag }, callback); - } - - // Open the file with same flags and mode as fs.writeFile() - fs.open(path, typeof options.flag === 'string' ? options.flag : 'r', options.mode, (openError, fd) => { - if (openError) { - return callback(openError); - } - - // It is valid to pass a fd handle to fs.writeFile() and this will keep the handle open! - fs.writeFile(fd, data, writeError => { - if (writeError) { - return fs.close(fd, () => callback(writeError)); // still need to close the handle on error! - } - - // Flush contents (not metadata) of the file to disk - fs.fdatasync(fd, (syncError: Error) => { - - // In some exotic setups it is well possible that node fails to sync - // In that case we disable flushing and warn to the console - if (syncError) { - console.warn('[node.js fs] fdatasync is now disabled for this session because it failed: ', syncError); - canFlush = false; - } - - return fs.close(fd, closeError => callback(closeError)); - }); - }); - }); -} - -export function writeFileAndFlushSync(path: string, data: string | Buffer, options?: IWriteFileOptions): void { - options = ensureOptions(options); - - if (options.encoding) { - data = encode(data, options.encoding.charset, { addBOM: options.encoding.addBOM }); - } - - if (!canFlush) { - return fs.writeFileSync(path, data, { mode: options.mode, flag: options.flag }); - } - - // Open the file with same flags and mode as fs.writeFile() - const fd = fs.openSync(path, typeof options.flag === 'string' ? options.flag : 'r', options.mode); - - try { - - // It is valid to pass a fd handle to fs.writeFile() and this will keep the handle open! - fs.writeFileSync(fd, data); - - // Flush contents (not metadata) of the file to disk - try { - fs.fdatasyncSync(fd); - } catch (syncError) { - console.warn('[node.js fs] fdatasyncSync is now disabled for this session because it failed: ', syncError); - canFlush = false; - } - } finally { - fs.closeSync(fd); - } -} - -function ensureOptions(options?: IWriteFileOptions): IWriteFileOptions { - if (!options) { - return { mode: 0o666, flag: 'w' }; - } - - const ensuredOptions: IWriteFileOptions = { mode: options.mode, flag: options.flag, encoding: options.encoding }; - - if (typeof ensuredOptions.mode !== 'number') { - ensuredOptions.mode = 0o666; - } - - if (typeof ensuredOptions.flag !== 'string') { - ensuredOptions.flag = 'w'; - } - - return ensuredOptions; -} - -/** - * Copied from: https://github.com/Microsoft/vscode-node-debug/blob/master/src/node/pathUtilities.ts#L83 - * - * Given an absolute, normalized, and existing file path 'realcase' returns the exact path that the file has on disk. - * On a case insensitive file system, the returned path might differ from the original path by character casing. - * On a case sensitive file system, the returned path will always be identical to the original path. - * In case of errors, null is returned. But you cannot use this function to verify that a path exists. - * realcaseSync does not handle '..' or '.' path segments and it does not take the locale into account. - */ -export function realcaseSync(path: string): string | null { - const dir = paths.dirname(path); - if (path === dir) { // end recursion - return path; - } - - const name = (paths.basename(path) /* can be '' for windows drive letters */ || path).toLowerCase(); - try { - const entries = readdirSync(dir); - const found = entries.filter(e => e.toLowerCase() === name); // use a case insensitive search - if (found.length === 1) { - // on a case sensitive filesystem we cannot determine here, whether the file exists or not, hence we need the 'file exists' precondition - const prefix = realcaseSync(dir); // recurse - if (prefix) { - return paths.join(prefix, found[0]); - } - } else if (found.length > 1) { - // must be a case sensitive $filesystem - const ix = found.indexOf(name); - if (ix >= 0) { // case sensitive - const prefix = realcaseSync(dir); // recurse - if (prefix) { - return paths.join(prefix, found[ix]); - } - } - } - } catch (error) { - // silently ignore error - } - - return null; -} - -export function realpathSync(path: string): string { - try { - return fs.realpathSync(path); - } catch (error) { - - // We hit an error calling fs.realpathSync(). Since fs.realpathSync() is doing some path normalization - // we now do a similar normalization and then try again if we can access the path with read - // permissions at least. If that succeeds, we return that path. - // fs.realpath() is resolving symlinks and that can fail in certain cases. The workaround is - // to not resolve links but to simply see if the path is read accessible or not. - const normalizedPath = normalizePath(path); - fs.accessSync(normalizedPath, fs.constants.R_OK); // throws in case of an error - - return normalizedPath; - } -} - -export function realpath(path: string, callback: (error: Error | null, realpath: string) => void): void { - return fs.realpath(path, (error, realpath) => { - if (!error) { - return callback(null, realpath); - } - - // We hit an error calling fs.realpath(). Since fs.realpath() is doing some path normalization - // we now do a similar normalization and then try again if we can access the path with read - // permissions at least. If that succeeds, we return that path. - // fs.realpath() is resolving symlinks and that can fail in certain cases. The workaround is - // to not resolve links but to simply see if the path is read accessible or not. - const normalizedPath = normalizePath(path); - - return fs.access(normalizedPath, fs.constants.R_OK, error => { - return callback(error, normalizedPath); - }); - }); -} - -function normalizePath(path: string): string { - return strings.rtrim(paths.normalize(path), paths.sep); -} - -export function watch(path: string, onChange: (type: string, path?: string) => void, onError: (error: string) => void): IDisposable { - try { - const watcher = fs.watch(path); - - watcher.on('change', (type, raw) => { - let file: string | undefined; - if (raw) { // https://github.com/Microsoft/vscode/issues/38191 - file = raw.toString(); - if (platform.isMacintosh) { - // Mac: uses NFD unicode form on disk, but we want NFC - // See also https://github.com/nodejs/node/issues/2165 - file = normalizeNFC(file); - } - } - - onChange(type, file); - }); - - watcher.on('error', (code: number, signal: string) => onError(`Failed to watch ${path} for changes (${code}, ${signal})`)); - - return toDisposable(() => { - watcher.removeAllListeners(); - watcher.close(); - }); - } catch (error) { - fs.exists(path, exists => { - if (exists) { - onError(`Failed to watch ${path} for changes (${error.toString()})`); - } - }); - } - - return Disposable.None; -} - -export function sanitizeFilePath(candidate: string, cwd: string): string { - - // Special case: allow to open a drive letter without trailing backslash - if (platform.isWindows && strings.endsWith(candidate, ':')) { - candidate += paths.sep; - } - - // Ensure absolute - if (!paths.isAbsolute(candidate)) { - candidate = paths.join(cwd, candidate); - } - - // Ensure normalized - candidate = paths.normalize(candidate); - - // Ensure no trailing slash/backslash - if (platform.isWindows) { - candidate = strings.rtrim(candidate, paths.sep); - - // Special case: allow to open drive root ('C:\') - if (strings.endsWith(candidate, ':')) { - candidate += paths.sep; - } - - } else { - candidate = strings.rtrim(candidate, paths.sep); - - // Special case: allow to open root ('/') - if (!candidate) { - candidate = paths.sep; - } - } - - return candidate; -} \ No newline at end of file diff --git a/src/vs/base/node/extpath.ts b/src/vs/base/node/extpath.ts new file mode 100644 index 00000000000..b3b55b7aaee --- /dev/null +++ b/src/vs/base/node/extpath.ts @@ -0,0 +1,91 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +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 + * + * Given an absolute, normalized, and existing file path 'realcase' returns the exact path that the file has on disk. + * On a case insensitive file system, the returned path might differ from the original path by character casing. + * On a case sensitive file system, the returned path will always be identical to the original path. + * In case of errors, null is returned. But you cannot use this function to verify that a path exists. + * realcaseSync does not handle '..' or '.' path segments and it does not take the locale into account. + */ +export function realcaseSync(path: string): string | null { + const dir = dirname(path); + if (path === dir) { // end recursion + return path; + } + + const name = (basename(path) /* can be '' for windows drive letters */ || path).toLowerCase(); + try { + const entries = readdirSync(dir); + const found = entries.filter(e => e.toLowerCase() === name); // use a case insensitive search + if (found.length === 1) { + // on a case sensitive filesystem we cannot determine here, whether the file exists or not, hence we need the 'file exists' precondition + const prefix = realcaseSync(dir); // recurse + if (prefix) { + return join(prefix, found[0]); + } + } else if (found.length > 1) { + // must be a case sensitive $filesystem + const ix = found.indexOf(name); + if (ix >= 0) { // case sensitive + const prefix = realcaseSync(dir); // recurse + if (prefix) { + return join(prefix, found[ix]); + } + } + } + } catch (error) { + // silently ignore error + } + + return null; +} + +export async function realpath(path: string): Promise { + try { + return await promisify(fs.realpath)(path); + } catch (error) { + + // We hit an error calling fs.realpath(). Since fs.realpath() is doing some path normalization + // we now do a similar normalization and then try again if we can access the path with read + // permissions at least. If that succeeds, we return that path. + // fs.realpath() is resolving symlinks and that can fail in certain cases. The workaround is + // 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); + + return normalizedPath; + } +} + +export function realpathSync(path: string): string { + try { + return fs.realpathSync(path); + } catch (error) { + + // We hit an error calling fs.realpathSync(). Since fs.realpathSync() is doing some path normalization + // we now do a similar normalization and then try again if we can access the path with read + // permissions at least. If that succeeds, we return that path. + // fs.realpath() is resolving symlinks and that can fail in certain cases. The workaround is + // to not resolve links but to simply see if the path is read accessible or not. + const normalizedPath = normalizePath(path); + fs.accessSync(normalizedPath, fs.constants.R_OK); // throws in case of an error + + return normalizedPath; + } +} + +function normalizePath(path: string): string { + return rtrim(normalize(path), sep); +} \ No newline at end of file diff --git a/src/vs/base/node/flow.ts b/src/vs/base/node/flow.ts deleted file mode 100644 index c1232c2993b..00000000000 --- a/src/vs/base/node/flow.ts +++ /dev/null @@ -1,187 +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 * as assert from 'assert'; - -/** - * Executes the given function (fn) over the given array of items (list) in parallel and returns the resulting errors and results as - * array to the callback (callback). The resulting errors and results are evaluated by calling the provided callback function. - */ -export function parallel(list: T[], fn: (item: T, callback: (err: Error | null, result: E | null) => void) => void, callback: (err: Array | null, result: E[]) => void): void { - let results = new Array(list.length); - let errors = new Array(list.length); - let didErrorOccur = false; - let doneCount = 0; - - if (list.length === 0) { - return callback(null, []); - } - - list.forEach((item, index) => { - fn(item, (error, result) => { - if (error) { - didErrorOccur = true; - results[index] = null; - errors[index] = error; - } else { - results[index] = result; - errors[index] = null; - } - - if (++doneCount === list.length) { - return callback(didErrorOccur ? errors : null, results); - } - }); - }); -} - -/** - * Executes the given function (fn) over the given array of items (param) in sequential order and returns the first occurred error or the result as - * array to the callback (callback). The resulting errors and results are evaluated by calling the provided callback function. The first param can - * either be a function that returns an array of results to loop in async fashion or be an array of items already. - */ -export function loop(param: (callback: (error: Error, result: T[]) => void) => void, fn: (item: T, callback: (error: Error | null, result: E | null) => void, index: number, total: number) => void, callback: (error: Error | null, result: E[] | null) => void): void; -export function loop(param: T[], fn: (item: T, callback: (error: Error | null, result: E | null) => void, index: number, total: number) => void, callback: (error: Error | null, result: E[] | null) => void): void; -export function loop(param: any, fn: (item: any, callback: (error: Error | null, result: E | null) => void, index: number, total: number) => void, callback: (error: Error | null, result: E[] | null) => void): void { - - // Assert - assert.ok(param, 'Missing first parameter'); - assert.ok(typeof (fn) === 'function', 'Second parameter must be a function that is called for each element'); - assert.ok(typeof (callback) === 'function', 'Third parameter must be a function that is called on error and success'); - - // Param is function, execute to retrieve array - if (typeof (param) === 'function') { - try { - param((error: Error, result: E[]) => { - if (error) { - callback(error, null); - } else { - loop(result, fn, callback); - } - }); - } catch (error) { - callback(error, null); - } - } - - // Expect the param to be an array and loop over it - else { - let results: E[] = []; - - let looper: (i: number) => void = function (i: number): void { - - // Still work to do - if (i < param.length) { - - // Execute function on array element - try { - fn(param[i], (error: any, result: E) => { - - // A method might only send a boolean value as return value (e.g. fs.exists), support this case gracefully - if (error === true || error === false) { - result = error; - error = null; - } - - // Quit looping on error - if (error) { - callback(error, null); - } - - // Otherwise push result on stack and continue looping - else { - if (result) { //Could be that provided function is not returning a result - results.push(result); - } - - process.nextTick(() => { - looper(i + 1); - }); - } - }, i, param.length); - } catch (error) { - callback(error, null); - } - } - - // Done looping, pass back results too callback function - else { - callback(null, results); - } - }; - - // Start looping with first element in array - looper(0); - } -} - -function Sequence(sequences: { (...param: any[]): void; }[]): void { - - // Assert - assert.ok(sequences.length > 1, 'Need at least one error handler and one function to process sequence'); - sequences.forEach((sequence) => { - assert.ok(typeof (sequence) === 'function'); - }); - - // Execute in Loop - let errorHandler = sequences.splice(0, 1)[0]; //Remove error handler - let sequenceResult: any = null; - - loop(sequences, (sequence, clb) => { - let sequenceFunction = function (error: any, result: any): void { - - // A method might only send a boolean value as return value (e.g. fs.exists), support this case gracefully - if (error === true || error === false) { - result = error; - error = null; - } - - // Handle Error and Result - if (error) { - clb(error, null); - } else { - sequenceResult = result; //Remember result of sequence - clb(null, null); //Don't pass on result to Looper as we are not aggregating it - } - }; - - // We call the sequence function setting "this" to be the callback we define here - // and we pass in the "sequenceResult" as first argument. Doing all this avoids having - // to pass in a callback to the sequence because the callback is already "this". - try { - sequence.call(sequenceFunction, sequenceResult); - } catch (error) { - clb(error, null); - } - }, (error, result) => { - if (error) { - errorHandler(error); - } - }); -} - -/** - * Takes a variable list of functions to execute in sequence. The first function must be the error handler and the - * following functions can do arbitrary work. "this" must be used as callback value for async functions to continue - * through the sequence: - * sequence( - * function errorHandler(error) { - * clb(error, null); - * }, - * - * function doSomethingAsync() { - * fs.doAsync(path, this); - * }, - * - * function done(result) { - * clb(null, result); - * } - * ); - */ -export function sequence(errorHandler: (error: Error) => void, ...sequences: Function[]): void; -export function sequence(sequences: Function[]): void; -export function sequence(sequences: any): void { - Sequence((Array.isArray(sequences)) ? sequences : Array.prototype.slice.call(arguments)); -} \ No newline at end of file diff --git a/src/vs/base/node/id.ts b/src/vs/base/node/id.ts index 1c7f84fa451..c2faa20632f 100644 --- a/src/vs/base/node/id.ts +++ b/src/vs/base/node/id.ts @@ -7,11 +7,12 @@ import * as errors from 'vs/base/common/errors'; import * as uuid from 'vs/base/common/uuid'; import { networkInterfaces } from 'os'; import { TernarySearchTree } from 'vs/base/common/map'; +import { getMac } from 'vs/base/node/macAddress'; // http://www.techrepublic.com/blog/data-center/mac-address-scorecard-for-common-virtual-machine-platforms/ // VMware ESX 3, Server, Workstation, Player 00-50-56, 00-0C-29, 00-05-69 // Microsoft Hyper-V, Virtual Server, Virtual PC 00-03-FF -// Parallells Desktop, Workstation, Server, Virtuozzo 00-1C-42 +// Parallels Desktop, Workstation, Server, Virtuozzo 00-1C-42 // Virtual Iron 4 00-0F-4B // Red Hat Xen 00-16-3E // Oracle VM 00-16-3E @@ -20,8 +21,8 @@ import { TernarySearchTree } from 'vs/base/common/map'; // Sun xVM VirtualBox 08-00-27 export const virtualMachineHint: { value(): number } = new class { - private _virtualMachineOUIs: TernarySearchTree; - private _value: number; + private _virtualMachineOUIs?: TernarySearchTree; + private _value?: number; private _isVirtualMachineMacAdress(mac: string): boolean { if (!this._virtualMachineOUIs) { @@ -76,35 +77,25 @@ export const virtualMachineHint: { value(): number } = new class { }; let machineId: Promise; -export function getMachineId(): Promise { - return machineId || (machineId = getMacMachineId() - .then(id => id || uuid.generateUuid())); // fallback, generate a UUID +export async function getMachineId(): Promise { + if (!machineId) { + machineId = (async () => { + const id = await getMacMachineId(); + + return id || uuid.generateUuid(); // fallback, generate a UUID + })(); + } + + return machineId; } -function getMacMachineId(): Promise { - return new Promise(resolve => { - Promise.all([import('crypto'), import('getmac')]).then(([crypto, getmac]) => { - try { - getmac.getMac((error, macAddress) => { - if (!error) { - resolve(crypto.createHash('sha256').update(macAddress, 'utf8').digest('hex')); - } else { - resolve(undefined); - } - }); - - // Timeout due to hang with reduced privileges #58392 - // TODO@sbatten: Remove this when getmac is patched - setTimeout(() => { - resolve(undefined); - }, 1000); - } catch (err) { - errors.onUnexpectedError(err); - resolve(undefined); - } - }, err => { - errors.onUnexpectedError(err); - resolve(undefined); - }); - }); +async function getMacMachineId(): Promise { + try { + const crypto = await import('crypto'); + const macAddress = await getMac(); + return crypto.createHash('sha256').update(macAddress, 'utf8').digest('hex'); + } catch (err) { + errors.onUnexpectedError(err); + return undefined; + } } diff --git a/src/vs/base/node/languagePacks.d.ts b/src/vs/base/node/languagePacks.d.ts new file mode 100644 index 00000000000..241392e5eca --- /dev/null +++ b/src/vs/base/node/languagePacks.d.ts @@ -0,0 +1,23 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export interface NLSConfiguration { + locale: string; + availableLanguages: { + [key: string]: string; + }; + pseudo?: boolean; +} + +export interface InternalNLSConfiguration extends NLSConfiguration { + _languagePackId: string; + _translationsConfigFile: string; + _cacheRoot: string; + _resolvedLanguagePackCoreLocation: string; + _corruptedFile: string; + _languagePackSupport?: boolean; +} + +export function getNLSConfiguration(commit: string, userDataPath: string, metaDataFile: string, locale: string): Promise; \ No newline at end of file diff --git a/src/vs/base/node/languagePacks.js b/src/vs/base/node/languagePacks.js new file mode 100644 index 00000000000..445a6c5f7b3 --- /dev/null +++ b/src/vs/base/node/languagePacks.js @@ -0,0 +1,332 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +//@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) { + + /** + * @param {string} file + * @returns {Promise} + */ + function exists(file) { + return new Promise(c => fs.exists(file, c)); + } + + /** + * @param {string} file + * @returns {Promise} + */ + 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} + */ + function lstat(file) { + return new Promise((c, e) => fs.lstat(file, (err, stats) => err ? e(err) : c(stats))); + } + + /** + * @param {string} dir + * @returns {Promise} + */ + function readdir(dir) { + return new Promise((c, e) => fs.readdir(dir, (err, files) => err ? e(err) : c(files))); + } + + /** + * @param {string} dir + * @returns {Promise} + */ + function mkdir(dir) { + return new Promise((c, e) => fs.mkdir(dir, err => (err && err.code !== 'EEXIST') ? e(err) : c(dir))); + } + + /** + * @param {string} dir + * @returns {Promise} + */ + function rmdir(dir) { + return new Promise((c, e) => fs.rmdir(dir, err => err ? e(err) : c(undefined))); + } + + /** + * @param {string} file + * @returns {Promise} + */ + function unlink(file) { + return new Promise((c, e) => fs.unlink(file, err => err ? e(err) : c(undefined))); + } + + /** + * @param {string} location + * @returns {Promise} + */ + 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; + }); + } + + /** + * @param {string} dir + * @returns {Promise} + */ + function mkdirp(dir) { + return mkdir(dir).then(null, err => { + if (err && err.code === 'ENOENT') { + const parent = path.dirname(dir); + + if (parent !== dir) { // if not arrived at root + return mkdirp(parent).then(() => mkdir(dir)); + } + } + + 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} + */ + 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. + } + 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); + } else { + return undefined; + } + } + } + } 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 }); + } + + 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('nlsGeneration:start'); + + const defaultResult = function (locale) { + perf.mark('nlsGeneration:end'); + return Promise.resolve({ locale: locale, availableLanguages: {} }); + }; + try { + if (!commit) { + return defaultResult(initialLocale); + } + 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); + } + 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('nlsGeneration:end'); + 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 (let bundle of bundles) { + const modules = metadata.bundles[bundle]; + const target = Object.create(null); + for (let 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('nlsGeneration:end'); + 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); + } + } + + 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'); +} \ No newline at end of file diff --git a/src/vs/base/node/macAddress.ts b/src/vs/base/node/macAddress.ts new file mode 100644 index 00000000000..dd36be22344 --- /dev/null +++ b/src/vs/base/node/macAddress.ts @@ -0,0 +1,69 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { exec } from 'child_process'; +import { isWindows } from 'vs/base/common/platform'; + +const cmdline = { + windows: 'getmac.exe', + unix: '/sbin/ifconfig -a || /sbin/ip link' +}; + +const invalidMacAddresses = [ + '00:00:00:00:00:00', + 'ff:ff:ff:ff:ff:ff', + 'ac:de:48:00:11:22' +]; + +function validateMacAddress(candidate: string): boolean { + let tempCandidate = candidate.replace(/\-/g, ':').toLowerCase(); + for (let invalidMacAddress of invalidMacAddresses) { + if (invalidMacAddress === tempCandidate) { + return false; + } + } + + return true; +} + +export function getMac(): Promise { + return new Promise(async (resolve, reject) => { + const timeout = setTimeout(() => reject('Unable to retrieve mac address (timeout after 10s)'), 10000); + + try { + resolve(await doGetMac()); + } catch (error) { + reject(error); + } finally { + clearTimeout(timeout); + } + }); +} + +function doGetMac(): Promise { + return new Promise((resolve, reject) => { + try { + exec(isWindows ? cmdline.windows : cmdline.unix, { timeout: 10000 }, (err, stdout, stdin) => { + if (err) { + return reject(`Unable to retrieve mac address (${err.toString()})`); + } else { + const regex = /(?:[a-f\d]{2}[:\-]){5}[a-f\d]{2}/gi; + + let match; + while ((match = regex.exec(stdout)) !== null) { + const macAddressCandidate = match[0]; + if (validateMacAddress(macAddressCandidate)) { + return resolve(macAddressCandidate); + } + } + + return reject('Unable to retrieve mac address (unexpected format)'); + } + }); + } catch (err) { + reject(err); + } + }); +} \ No newline at end of file diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index 5c4120904f6..1af9f028c70 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -3,64 +3,214 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as extfs from 'vs/base/node/extfs'; -import { join } from 'path'; -import { nfcall, Queue } from 'vs/base/common/async'; +import { join, dirname } from 'vs/base/common/path'; +import { Queue } from 'vs/base/common/async'; import * as fs from 'fs'; import * as os from 'os'; import * as platform from 'vs/base/common/platform'; import { Event } from 'vs/base/common/event'; +import { endsWith } from 'vs/base/common/strings'; +import { promisify } from 'util'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { isRootOrDriveLetter } from 'vs/base/common/extpath'; +import { generateUuid } from 'vs/base/common/uuid'; +import { normalizeNFC } from 'vs/base/common/normalization'; +import { encode, encodeStream } from 'vs/base/node/encoding'; -export function readdir(path: string): Promise { - return nfcall(extfs.readdir, path); +export enum RimRafMode { + + /** + * Slow version that unlinks each file and folder. + */ + UNLINK, + + /** + * Fast version that first moves the file/folder + * into a temp directory and then deletes that + * without waiting for it. + */ + MOVE +} + +export async function rimraf(path: string, mode = RimRafMode.UNLINK): Promise { + if (isRootOrDriveLetter(path)) { + throw new Error('rimraf - will refuse to recursively delete root'); + } + + // delete: via unlink + if (mode === RimRafMode.UNLINK) { + return rimrafUnlink(path); + } + + // delete: via move + return rimrafMove(path); +} + +async function rimrafUnlink(path: string): Promise { + 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); + } + + // Single file delete + else { + + // chmod as needed to allow for unlink + const mode = stat.mode; + if (!(mode & 128)) { // 128 === 0200 + await chmod(path, mode | 128); + } + + return unlink(path); + } + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } +} + +async function rimrafMove(path: string): Promise { + try { + const pathInTemp = join(os.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; + } + } +} + +export function rimrafSync(path: string): void { + if (isRootOrDriveLetter(path)) { + throw new Error('rimraf - will refuse to recursively delete root'); + } + + 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 & 128)) { // 128 === 0200 + fs.chmodSync(path, mode | 128); + } + + return fs.unlinkSync(path); + } + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } +} + +export async function readdir(path: string): Promise { + return handleDirectoryChildren(await promisify(fs.readdir)(path)); +} + +export async function readdirWithFileTypes(path: string): Promise { + 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 (platform.isMacintosh) { + for (const child of children) { + child.name = normalizeNFC(child.name); + } + } + + return children; +} + +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 (platform.isMacintosh) { + return children.map(child => normalizeNFC(child)); + } + + return children; } export function exists(path: string): Promise { - return new Promise(c => fs.exists(path, c)); + return promisify(fs.exists)(path); } -export function chmod(path: string, mode: number): Promise { - return nfcall(fs.chmod, path, mode); -} - -export import mkdirp = extfs.mkdirp; - -export function rimraf(path: string): Promise { - return lstat(path).then(stat => { - if (stat.isDirectory() && !stat.isSymbolicLink()) { - return readdir(path) - .then(children => Promise.all(children.map(child => rimraf(join(path, child))))) - .then(() => rmdir(path)); - } else { - return unlink(path); - } - }, (err: NodeJS.ErrnoException) => { - if (err.code === 'ENOENT') { - return undefined; - } - - return Promise.reject(err); - }); -} - -export function realpath(path: string): Promise { - return nfcall(extfs.realpath, path); +export function chmod(path: string, mode: number): Promise { + return promisify(fs.chmod)(path, mode); } export function stat(path: string): Promise { - return nfcall(fs.stat, path); + return promisify(fs.stat)(path); } -export function statLink(path: string): Promise<{ stat: fs.Stats, isSymbolicLink: boolean }> { - return nfcall(extfs.statLink, path); +export interface IStatAndLink { + stat: fs.Stats; + isSymbolicLink: boolean; +} + +export async function statLink(path: string): Promise { + + // First stat the link + let linkStat: fs.Stats | undefined; + let linkStatError: NodeJS.ErrnoException | undefined; + try { + linkStat = await lstat(path); + } catch (error) { + linkStatError = error; + } + + // Then stat the target and return that + const isLink = !!(linkStat && linkStat.isSymbolicLink()); + if (linkStatError || isLink) { + const fileStat = await stat(path); + + return { stat: fileStat, isSymbolicLink: isLink }; + } + + return { stat: linkStat!, isSymbolicLink: false }; } export function lstat(path: string): Promise { - return nfcall(fs.lstat, path); + return promisify(fs.lstat)(path); } export function rename(oldPath: string, newPath: string): Promise { - return nfcall(fs.rename, oldPath, newPath); + return promisify(fs.rename)(oldPath, newPath); } export function renameIgnoreError(oldPath: string, newPath: string): Promise { @@ -69,52 +219,38 @@ export function renameIgnoreError(oldPath: string, newPath: string): Promise { - return nfcall(fs.rmdir, path); -} - export function unlink(path: string): Promise { - return nfcall(fs.unlink, path); -} - -export function unlinkIgnoreError(path: string): Promise { - return new Promise(resolve => { - fs.unlink(path, () => resolve()); - }); + return promisify(fs.unlink)(path); } export function symlink(target: string, path: string, type?: string): Promise { - return nfcall(fs.symlink, target, path, type); -} - -export function readlink(path: string): Promise { - return nfcall(fs.readlink, path); + return promisify(fs.symlink)(target, path, type); } export function truncate(path: string, len: number): Promise { - return nfcall(fs.truncate, path, len); + return promisify(fs.truncate)(path, len); } export function readFile(path: string): Promise; export function readFile(path: string, encoding: string): Promise; export function readFile(path: string, encoding?: string): Promise { - return nfcall(fs.readFile, path, encoding); + return promisify(fs.readFile)(path, encoding); } // 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 writeFilePathQueue: { [path: string]: Queue } = Object.create(null); +const writeFilePathQueues: Map> = new Map(); -export function writeFile(path: string, data: string, options?: extfs.IWriteFileOptions): Promise; -export function writeFile(path: string, data: Buffer, options?: extfs.IWriteFileOptions): Promise; -export function writeFile(path: string, data: Uint8Array, options?: extfs.IWriteFileOptions): Promise; -export function writeFile(path: string, data: NodeJS.ReadableStream, options?: extfs.IWriteFileOptions): Promise; -export function writeFile(path: string, data: any, options?: extfs.IWriteFileOptions): Promise; -export function writeFile(path: string, data: any, options?: extfs.IWriteFileOptions): any { +export function writeFile(path: string, data: string, options?: IWriteFileOptions): Promise; +export function writeFile(path: string, data: Buffer, options?: IWriteFileOptions): Promise; +export function writeFile(path: string, data: Uint8Array, options?: IWriteFileOptions): Promise; +export function writeFile(path: string, data: NodeJS.ReadableStream, options?: IWriteFileOptions): Promise; +export function writeFile(path: string, data: string | Buffer | NodeJS.ReadableStream | Uint8Array, options?: IWriteFileOptions): Promise; +export function writeFile(path: string, data: string | Buffer | NodeJS.ReadableStream | Uint8Array, options?: IWriteFileOptions): Promise { const queueKey = toQueueKey(path); - return ensureWriteFileQueue(queueKey).queue(() => nfcall(extfs.writeFileAndFlush, path, data, options)); + return ensureWriteFileQueue(queueKey).queue(() => writeFileAndFlush(path, data, options)); } function toQueueKey(path: string): string { @@ -127,58 +263,252 @@ function toQueueKey(path: string): string { } function ensureWriteFileQueue(queueKey: string): Queue { - let writeFileQueue = writeFilePathQueue[queueKey]; - if (!writeFileQueue) { - writeFileQueue = new Queue(); - writeFilePathQueue[queueKey] = writeFileQueue; - - const onFinish = Event.once(writeFileQueue.onFinished); - onFinish(() => { - delete writeFilePathQueue[queueKey]; - writeFileQueue.dispose(); - }); + const existingWriteFileQueue = writeFilePathQueues.get(queueKey); + if (existingWriteFileQueue) { + return existingWriteFileQueue; } + const writeFileQueue = new Queue(); + writeFilePathQueues.set(queueKey, writeFileQueue); + + const onFinish = Event.once(writeFileQueue.onFinished); + onFinish(() => { + writeFilePathQueues.delete(queueKey); + writeFileQueue.dispose(); + }); + return writeFileQueue; } -/** -* Read a dir and return only subfolders -*/ -export function readDirsInDir(dirPath: string): Promise { - return readdir(dirPath).then(children => { - return Promise.all(children.map(c => dirExists(join(dirPath, c)))).then(exists => { - return children.filter((_, i) => exists[i]); +export interface IWriteFileOptions { + mode?: number; + flag?: string; + encoding?: { + charset: string; + addBOM: boolean; + }; +} + +interface IEnsuredWriteFileOptions extends IWriteFileOptions { + mode: number; + flag: string; +} + +let canFlush = true; +function writeFileAndFlush(path: string, data: string | Buffer | NodeJS.ReadableStream | Uint8Array, options: IWriteFileOptions | undefined): Promise { + const ensuredOptions = ensureWriteOptions(options); + + return new Promise((resolve, reject) => { + if (typeof data === 'string' || Buffer.isBuffer(data) || data instanceof Uint8Array) { + doWriteFileAndFlush(path, data, ensuredOptions, error => error ? reject(error) : resolve()); + } else { + doWriteFileStreamAndFlush(path, data, ensuredOptions, error => error ? reject(error) : resolve()); + } + }); +} + +function doWriteFileStreamAndFlush(path: string, reader: NodeJS.ReadableStream, options: IEnsuredWriteFileOptions, callback: (error?: Error) => void): void { + + // finish only once + let finished = false; + const finish = (error?: Error) => { + if (!finished) { + finished = true; + + // in error cases we need to manually close streams + // if the write stream was successfully opened + if (error) { + if (isOpen) { + writer.once('close', () => callback(error)); + writer.destroy(); + } else { + callback(error); + } + } + + // otherwise just return without error + else { + callback(); + } + } + }; + + // create writer to target. we set autoClose: false because we want to use the streams + // file descriptor to call fs.fdatasync to ensure the data is flushed to disk + const writer = fs.createWriteStream(path, { mode: options.mode, flags: options.flag, autoClose: false }); + + // Event: 'open' + // Purpose: save the fd for later use and start piping + // Notes: will not be called when there is an error opening the file descriptor! + let fd: number; + let isOpen: boolean; + writer.once('open', descriptor => { + fd = descriptor; + isOpen = true; + + // if an encoding is provided, we need to pipe the stream through + // an encoder stream and forward the encoding related options + if (options.encoding) { + reader = reader.pipe(encodeStream(options.encoding.charset, { addBOM: options.encoding.addBOM })); + } + + // start data piping only when we got a successful open. this ensures that we do + // not consume the stream when an error happens and helps to fix this issue: + // https://github.com/Microsoft/vscode/issues/42542 + reader.pipe(writer); + }); + + // Event: 'error' + // Purpose: to return the error to the outside and to close the write stream (does not happen automatically) + reader.once('error', error => finish(error)); + writer.once('error', error => finish(error)); + + // Event: 'finish' + // Purpose: use fs.fdatasync to flush the contents to disk + // Notes: event is called when the writer has finished writing to the underlying resource. we must call writer.close() + // because we have created the WriteStream with autoClose: false + writer.once('finish', () => { + + // flush to disk + if (canFlush && isOpen) { + fs.fdatasync(fd, (syncError: Error) => { + + // In some exotic setups it is well possible that node fails to sync + // In that case we disable flushing and warn to the console + if (syncError) { + console.warn('[node.js fs] fdatasync is now disabled for this session because it failed: ', syncError); + canFlush = false; + } + + writer.destroy(); + }); + } else { + writer.destroy(); + } + }); + + // Event: 'close' + // Purpose: signal we are done to the outside + // Notes: event is called when the writer's filedescriptor is closed + writer.once('close', () => finish()); +} + +// Calls fs.writeFile() followed by a fs.sync() call to flush the changes to disk +// We do this in cases where we want to make sure the data is really on disk and +// not in some cache. +// +// See https://github.com/nodejs/node/blob/v5.10.0/lib/fs.js#L1194 +function doWriteFileAndFlush(path: string, data: string | Buffer | Uint8Array, options: IEnsuredWriteFileOptions, callback: (error?: Error) => void): void { + if (options.encoding) { + data = encode(data instanceof Uint8Array ? Buffer.from(data) : data, options.encoding.charset, { addBOM: options.encoding.addBOM }); + } + + if (!canFlush) { + return fs.writeFile(path, data, { mode: options.mode, flag: options.flag }, callback); + } + + // Open the file with same flags and mode as fs.writeFile() + fs.open(path, options.flag, options.mode, (openError, fd) => { + if (openError) { + return callback(openError); + } + + // It is valid to pass a fd handle to fs.writeFile() and this will keep the handle open! + fs.writeFile(fd, data, writeError => { + if (writeError) { + return fs.close(fd, () => callback(writeError)); // still need to close the handle on error! + } + + // Flush contents (not metadata) of the file to disk + fs.fdatasync(fd, (syncError: Error) => { + + // In some exotic setups it is well possible that node fails to sync + // In that case we disable flushing and warn to the console + if (syncError) { + console.warn('[node.js fs] fdatasync is now disabled for this session because it failed: ', syncError); + canFlush = false; + } + + return fs.close(fd, closeError => callback(closeError)); + }); }); }); } -/** -* `path` exists and is a directory -*/ -export function dirExists(path: string): Promise { - return stat(path).then(stat => stat.isDirectory(), () => false); -} +export function writeFileSync(path: string, data: string | Buffer, options?: IWriteFileOptions): void { + const ensuredOptions = ensureWriteOptions(options); -/** -* `path` exists and is a file. -*/ -export function fileExists(path: string): Promise { - return stat(path).then(stat => stat.isFile(), () => false); -} - -/** - * Deletes a path from disk. - */ -let _tmpDir: string | null = null; -function getTmpDir(): string { - if (!_tmpDir) { - _tmpDir = os.tmpdir(); + if (ensuredOptions.encoding) { + data = encode(data, ensuredOptions.encoding.charset, { addBOM: ensuredOptions.encoding.addBOM }); + } + + if (!canFlush) { + return fs.writeFileSync(path, data, { mode: ensuredOptions.mode, flag: ensuredOptions.flag }); + } + + // Open the file with same flags and mode as fs.writeFile() + const fd = fs.openSync(path, ensuredOptions.flag, ensuredOptions.mode); + + try { + + // It is valid to pass a fd handle to fs.writeFile() and this will keep the handle open! + fs.writeFileSync(fd, data); + + // Flush contents (not metadata) of the file to disk + try { + fs.fdatasyncSync(fd); + } catch (syncError) { + console.warn('[node.js fs] fdatasyncSync is now disabled for this session because it failed: ', syncError); + canFlush = false; + } + } finally { + fs.closeSync(fd); } - return _tmpDir; } -export function del(path: string, tmp = getTmpDir()): Promise { - return nfcall(extfs.del, path, tmp); + +function ensureWriteOptions(options?: IWriteFileOptions): IEnsuredWriteFileOptions { + if (!options) { + return { mode: 0o666, flag: 'w' }; + } + + return { + mode: typeof options.mode === 'number' ? options.mode : 0o666, + flag: typeof options.flag === 'string' ? options.flag : 'w', + encoding: options.encoding + }; +} + +export async function readDirsInDir(dirPath: string): Promise { + const children = await readdir(dirPath); + const directories: string[] = []; + + for (const child of children) { + if (await dirExists(join(dirPath, child))) { + directories.push(child); + } + } + + return directories; +} + +export async function dirExists(path: string): Promise { + try { + const fileStat = await stat(path); + + return fileStat.isDirectory(); + } catch (error) { + return false; + } +} + +export async function fileExists(path: string): Promise { + try { + const fileStat = await stat(path); + + return fileStat.isFile(); + } catch (error) { + return false; + } } export function whenDeleted(path: string): Promise { @@ -202,6 +532,165 @@ export function whenDeleted(path: string): Promise { }); } -export function copy(source: string, target: string): Promise { - return nfcall(extfs.copy, source, target); +export async function move(source: string, target: string): Promise { + if (source === target) { + return Promise.resolve(); + } + + async function updateMtime(path: string): Promise { + const stat = await lstat(path); + if (stat.isDirectory() || stat.isSymbolicLink()) { + return Promise.resolve(); // only for files + } + + const fd = await promisify(fs.open)(path, 'a'); + try { + await promisify(fs.futimes)(fd, stat.atime, new Date()); + } catch (error) { + //ignore + } + + return promisify(fs.close)(fd); + } + + try { + await rename(source, target); + await updateMtime(target); + } catch (error) { + + // In two cases we fallback to classic copy and delete: + // + // 1.) The EXDEV error indicates that source and target are on different devices + // In this case, fallback to using a copy() operation as there is no way to + // rename() between different devices. + // + // 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' || endsWith(source, '.')) { + await copy(source, target); + await rimraf(source, RimRafMode.MOVE); + await updateMtime(target); + } else { + throw error; + } + } } + +export async function copy(source: string, target: string, copiedSourcesIn?: { [path: string]: boolean }): Promise { + const copiedSources = copiedSourcesIn ? copiedSourcesIn : Object.create(null); + + const fileStat = await stat(source); + if (!fileStat.isDirectory()) { + return doCopyFile(source, target, fileStat.mode & 511); + } + + if (copiedSources[source]) { + return Promise.resolve(); // escape when there are cycles (can happen with symlinks) + } + + copiedSources[source] = true; // remember as copied + + // Create folder + await mkdirp(target, fileStat.mode & 511); + + // 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), copiedSources); + } +} + +async function doCopyFile(source: string, target: string, mode: number): Promise { + 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; + + // 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); + }); +} + +export async function mkdirp(path: string, mode?: number, token?: CancellationToken): Promise { + const mkdir = async () => { + try { + await promisify(fs.mkdir)(path, mode); + } catch (error) { + + // ENOENT: a parent folder does not exist yet + if (error.code === 'ENOENT') { + return Promise.reject(error); + } + + // Any other error: check if folder exists and + // return normally in that case if its a folder + try { + const fileStat = await stat(path); + if (!fileStat.isDirectory()) { + return Promise.reject(new Error(`'${path}' exists and is not a directory.`)); + } + } catch (statError) { + throw error; // rethrow original error + } + } + }; + + // stop at root + if (path === dirname(path)) { + return Promise.resolve(); + } + + try { + await mkdir(); + } catch (error) { + + // Respect cancellation + if (token && token.isCancellationRequested) { + return Promise.resolve(); + } + + // ENOENT: a parent folder does not exist yet, continue + // to create the parent folder and then try again. + if (error.code === 'ENOENT') { + await mkdirp(dirname(path), mode); + + return mkdir(); + } + + // Any other error + return Promise.reject(error); + } +} + +// See https://github.com/Microsoft/vscode/issues/30180 +const WIN32_MAX_FILE_SIZE = 300 * 1024 * 1024; // 300 MB +const GENERAL_MAX_FILE_SIZE = 16 * 1024 * 1024 * 1024; // 16 GB + +// See https://github.com/v8/v8/blob/5918a23a3d571b9625e5cce246bdd5b46ff7cd8b/src/heap/heap.cc#L149 +const WIN32_MAX_HEAP_SIZE = 700 * 1024 * 1024; // 700 MB +const GENERAL_MAX_HEAP_SIZE = 700 * 2 * 1024 * 1024; // 1400 MB + +export const MAX_FILE_SIZE = process.arch === 'ia32' ? WIN32_MAX_FILE_SIZE : GENERAL_MAX_FILE_SIZE; +export const MAX_HEAP_SIZE = process.arch === 'ia32' ? WIN32_MAX_HEAP_SIZE : GENERAL_MAX_HEAP_SIZE; \ No newline at end of file diff --git a/src/vs/base/node/ports.ts b/src/vs/base/node/ports.ts index a077f020fa9..d0334628e47 100644 --- a/src/vs/base/node/ports.ts +++ b/src/vs/base/node/ports.ts @@ -9,8 +9,8 @@ import * as net from 'net'; * @returns Returns a random port between 1025 and 65535. */ export function randomPort(): number { - let min = 1025; - let max = 65535; + const min = 1025; + const max = 65535; return min + Math.floor((max - min) * Math.random()); } diff --git a/src/vs/base/node/processes.ts b/src/vs/base/node/processes.ts index 36b95e0f378..5bee9f9eced 100644 --- a/src/vs/base/node/processes.ts +++ b/src/vs/base/node/processes.ts @@ -3,14 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as path from 'path'; +import * as path from 'vs/base/common/path'; import * as fs from 'fs'; +import { promisify } from 'util'; import * as cp from 'child_process'; import * as nls from 'vs/nls'; import * as Types from 'vs/base/common/types'; import { IStringDictionary } from 'vs/base/common/collections'; import * as Objects from 'vs/base/common/objects'; -import * as TPath from 'vs/base/common/paths'; +import * as extpath from 'vs/base/common/extpath'; import * as Platform from 'vs/base/common/platform'; import { LineDecoder } from 'vs/base/node/decoder'; import { CommandOptions, ForkOptions, SuccessData, Source, TerminateResponse, TerminateResponseCode, Executable } from 'vs/base/common/processes'; @@ -42,7 +43,7 @@ function getWindowsCode(status: number): TerminateResponseCode { export function terminateProcess(process: cp.ChildProcess, cwd?: string): TerminateResponse { if (Platform.isWindows) { try { - let options: any = { + const options: any = { stdio: ['pipe', 'pipe', 'ignore'] }; if (cwd) { @@ -54,8 +55,8 @@ export function terminateProcess(process: cp.ChildProcess, cwd?: string): Termin } } else if (Platform.isLinux || Platform.isMacintosh) { try { - let cmd = getPathFromAmdModule(require, 'vs/base/node/terminateProcess.sh'); - let result = cp.spawnSync(cmd, [process.pid.toString()]); + const cmd = getPathFromAmdModule(require, 'vs/base/node/terminateProcess.sh'); + const result = cp.spawnSync(cmd, [process.pid.toString()]); if (result.error) { return { success: false, error: result.error }; } @@ -113,7 +114,7 @@ export abstract class AbstractProcess { this.shell = arg3; this.options = arg4; } else { - let executable = arg1; + const executable = arg1; this.cmd = executable.command; this.shell = executable.isShellCommand; this.args = executable.args.slice(0); @@ -124,7 +125,7 @@ export abstract class AbstractProcess { this.terminateRequested = false; if (this.options.env) { - let newEnv: IStringDictionary = Object.create(null); + const newEnv: IStringDictionary = Object.create(null); Object.keys(process.env).forEach((key) => { newEnv[key] = process.env[key]!; }); @@ -137,7 +138,7 @@ export abstract class AbstractProcess { public getSanitizedCommand(): string { let result = this.cmd.toLowerCase(); - let index = result.lastIndexOf(path.sep); + const index = result.lastIndexOf(path.sep); if (index !== -1) { result = result.substring(index + 1); } @@ -148,13 +149,13 @@ export abstract class AbstractProcess { } public start(pp: ProgressCallback): Promise { - if (Platform.isWindows && ((this.options && this.options.cwd && TPath.isUNC(this.options.cwd)) || !this.options && TPath.isUNC(process.cwd()))) { + if (Platform.isWindows && ((this.options && this.options.cwd && extpath.isUNC(this.options.cwd)) || !this.options && extpath.isUNC(process.cwd()))) { return Promise.reject(new Error(nls.localize('TaskRunner.UNC', 'Can\'t execute a shell command on a UNC drive.'))); } return this.useExec().then((useExec) => { let cc: ValueCallback; let ee: ErrorCallback; - let result = new Promise((c, e) => { + const result = new Promise((c, e) => { cc = c; ee = e; }); @@ -166,7 +167,7 @@ export abstract class AbstractProcess { } this.childProcess = cp.exec(cmd, this.options, (error, stdout, stderr) => { this.childProcess = null; - let err: any = error; + const err: any = error; // This is tricky since executing a command shell reports error back in case the executed command return an // error or the command didn't exist at all. So we can't blindly treat an error as a failed command. So we // always parse the output and report success unless the job got killed. @@ -178,11 +179,11 @@ export abstract class AbstractProcess { }); } else { let childProcess: cp.ChildProcess | null = null; - let closeHandler = (data: any) => { + const closeHandler = (data: any) => { this.childProcess = null; this.childProcessPromise = null; this.handleClose(data, cc, pp, ee); - let result: SuccessData = { + const result: SuccessData = { terminated: this.terminateRequested }; if (Types.isNumber(data)) { @@ -191,12 +192,12 @@ export abstract class AbstractProcess { cc(result); }; if (this.shell && Platform.isWindows) { - let options: any = Objects.deepClone(this.options); + const options: any = Objects.deepClone(this.options); options.windowsVerbatimArguments = true; options.detached = false; let quotedCommand: boolean = false; let quotedArg: boolean = false; - let commandLine: string[] = []; + const commandLine: string[] = []; let quoted = this.ensureQuotes(this.cmd); commandLine.push(quoted.value); quotedCommand = quoted.quoted; @@ -207,7 +208,7 @@ export abstract class AbstractProcess { quotedArg = quotedArg && quoted.quoted; }); } - let args: string[] = [ + const args: string[] = [ '/s', '/c', ]; @@ -287,7 +288,7 @@ export abstract class AbstractProcess { } return this.childProcessPromise.then((childProcess) => { this.terminateRequested = true; - let result = terminateProcess(childProcess, this.options.cwd); + const result = terminateProcess(childProcess, this.options.cwd); if (result.success) { this.childProcess = null; } @@ -300,14 +301,14 @@ export abstract class AbstractProcess { private useExec(): Promise { return new Promise((c, e) => { if (!this.shell || !Platform.isWindows) { - c(false); + return c(false); } - let cmdShell = cp.spawn(getWindowsShell(), ['/s', '/c']); + const cmdShell = cp.spawn(getWindowsShell(), ['/s', '/c']); cmdShell.on('error', (error: Error) => { - c(true); + return c(true); }); cmdShell.on('exit', (data: any) => { - c(false); + return c(false); }); }); } @@ -326,12 +327,12 @@ export class LineProcess extends AbstractProcess { protected handleExec(cc: ValueCallback, pp: ProgressCallback, error: Error, stdout: Buffer, stderr: Buffer) { [stdout, stderr].forEach((buffer: Buffer, index: number) => { - let lineDecoder = new LineDecoder(); - let lines = lineDecoder.write(buffer); + const lineDecoder = new LineDecoder(); + const lines = lineDecoder.write(buffer); lines.forEach((line) => { pp({ line: line, source: index === 0 ? Source.stdout : Source.stderr }); }); - let line = lineDecoder.end(); + const line = lineDecoder.end(); if (line) { pp({ line: line, source: index === 0 ? Source.stdout : Source.stderr }); } @@ -343,11 +344,11 @@ export class LineProcess extends AbstractProcess { this.stdoutLineDecoder = new LineDecoder(); this.stderrLineDecoder = new LineDecoder(); childProcess.stdout.on('data', (data: Buffer) => { - let lines = this.stdoutLineDecoder.write(data); + const lines = this.stdoutLineDecoder.write(data); lines.forEach(line => pp({ line: line, source: Source.stdout })); }); childProcess.stderr.on('data', (data: Buffer) => { - let lines = this.stderrLineDecoder.write(data); + const lines = this.stderrLineDecoder.write(data); lines.forEach(line => pp({ line: line, source: Source.stderr })); }); } @@ -380,7 +381,7 @@ export function createQueuedSender(childProcess: cp.ChildProcess): IQueuedSender return; } - let result = childProcess.send(msg, (error: Error) => { + const result = childProcess.send(msg, (error: Error) => { if (error) { console.error(error); // unlikely to happen, best we can do is log this error } @@ -404,7 +405,7 @@ export function createQueuedSender(childProcess: cp.ChildProcess): IQueuedSender } export namespace win32 { - export function findExecutable(command: string, cwd?: string, paths?: string[]): string { + export async function findExecutable(command: string, cwd?: string, paths?: string[]): Promise { // If we have an absolute path then we take it. if (path.isAbsolute(command)) { return command; @@ -412,7 +413,7 @@ export namespace win32 { if (cwd === undefined) { cwd = process.cwd(); } - let dir = path.dirname(command); + const dir = path.dirname(command); if (dir !== '.') { // We have a directory and the directory is relative (see above). Make the path absolute // to the current working directory. @@ -435,18 +436,18 @@ export namespace win32 { } else { fullPath = path.join(cwd, pathEntry, command); } - if (fs.existsSync(fullPath)) { + if (await promisify(fs.exists)(fullPath)) { return fullPath; } let withExtension = fullPath + '.com'; - if (fs.existsSync(withExtension)) { + if (await promisify(fs.exists)(withExtension)) { return withExtension; } withExtension = fullPath + '.exe'; - if (fs.existsSync(withExtension)) { + if (await promisify(fs.exists)(withExtension)) { return withExtension; } } return path.join(cwd, command); } -} \ No newline at end of file +} diff --git a/src/vs/base/node/ps.sh b/src/vs/base/node/ps.sh new file mode 100755 index 00000000000..4fe31039c5a --- /dev/null +++ b/src/vs/base/node/ps.sh @@ -0,0 +1,39 @@ +#!/bin/sh +PAGESIZE=`getconf PAGESIZE`; +TOTAL_MEMORY=`cat /proc/meminfo | head -n 1 | awk '{print $2}'`; + +# Mimic the output of ps -ax -o pid=,ppid=,pcpu=,pmem=,command= +# Read all numeric subdirectories in /proc +for pid in `cd /proc && ls -d [0-9]*` + do { + if [ -e /proc/$pid/stat ] + then + echo $pid; + + # ppid is the word at index 4 in the stat file for the process + awk '{print $4}' /proc/$pid/stat; + + # pcpu - calculation will be done later, this is a placeholder value + echo "0.0" + + # pmem - ratio of the process's working set size to total memory. + # use the page size to convert to bytes, total memory is in KB + # multiplied by 100 to get percentage, extra 10 to be able to move + # the decimal over by one place + RESIDENT_SET_SIZE=`awk '{print $24}' /proc/$pid/stat`; + PERCENT_MEMORY=$(((1000 * $PAGESIZE * $RESIDENT_SET_SIZE) / ($TOTAL_MEMORY * 1024))); + if [ $PERCENT_MEMORY -lt 10 ] + then + # replace the last character with 0. the last character + echo $PERCENT_MEMORY | sed 's/.$/0.&/'; #pmem + else + # insert . before the last character + echo $PERCENT_MEMORY | sed 's/.$/.&/'; + fi + + # cmdline + xargs -0 < /proc/$pid/cmdline; + fi + } | tr "\n" "\t"; # Replace newlines with tab so that all info for a process is shown on one line + echo; # But add new lines between processes +done diff --git a/src/vs/base/node/ps.ts b/src/vs/base/node/ps.ts index 7d7d0432428..55c3a73da57 100644 --- a/src/vs/base/node/ps.ts +++ b/src/vs/base/node/ps.ts @@ -4,27 +4,17 @@ *--------------------------------------------------------------------------------------------*/ import { exec } from 'child_process'; - +import { ProcessItem } from 'vs/base/common/processes'; import { getPathFromAmdModule } from 'vs/base/common/amd'; -export interface ProcessItem { - name: string; - cmd: string; - pid: number; - ppid: number; - load: number; - mem: number; - - children?: ProcessItem[]; -} - export function listProcesses(rootPid: number): Promise { return new Promise((resolve, reject) => { - let rootItem: ProcessItem; + let rootItem: ProcessItem | undefined; const map = new Map(); + function addToTree(pid: number, ppid: number, cmd: string, load: number, mem: number) { const parent = map.get(ppid); @@ -109,7 +99,7 @@ export function listProcesses(rootPid: number): Promise { } while (matches); if (result) { - if (cmd.indexOf('node ') !== 0) { + if (cmd.indexOf('node ') < 0 && cmd.indexOf('node.exe') < 0) { return `electron_node ${result}`; } } @@ -151,7 +141,7 @@ export function listProcesses(rootPid: number): Promise { rootItem = processItems.get(rootPid); if (rootItem) { processItems.forEach(item => { - let parent = processItems.get(item.ppid); + const parent = processItems.get(item.ppid); if (parent) { if (!parent.children) { parent.children = []; @@ -173,64 +163,87 @@ export function listProcesses(rootPid: number): Promise { }, windowsProcessTree.ProcessDataFlag.CommandLine | windowsProcessTree.ProcessDataFlag.Memory); }); } else { // OS X & Linux - - const CMD = '/bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,command='; - const PID_CMD = /^\s*([0-9]+)\s+([0-9]+)\s+([0-9]+\.[0-9]+)\s+([0-9]+\.[0-9]+)\s+(.+)$/; - - // Set numeric locale to ensure '.' is used as the decimal separator - exec(CMD, { maxBuffer: 1000 * 1024, env: { LC_NUMERIC: 'en_US.UTF-8' } }, (err, stdout, stderr) => { - - if (err || stderr) { - reject(err || stderr.toString()); - } else { - - const lines = stdout.toString().split('\n'); - for (const line of lines) { - let matches = PID_CMD.exec(line.trim()); - if (matches && matches.length === 6) { - addToTree(parseInt(matches[1]), parseInt(matches[2]), matches[5], parseFloat(matches[3]), parseFloat(matches[4])); + function calculateLinuxCpuUsage() { + // Flatten rootItem to get a list of all VSCode processes + let processes = [rootItem]; + const pids: number[] = []; + while (processes.length) { + const process = processes.shift(); + if (process) { + pids.push(process.pid); + if (process.children) { + processes = processes.concat(process.children); } } + } - if (process.platform === 'linux') { - // Flatten rootItem to get a list of all VSCode processes - let processes = [rootItem]; - const pids: number[] = []; - while (processes.length) { - const process = processes.shift(); - if (process) { - pids.push(process.pid); - if (process.children) { - processes = processes.concat(process.children); - } - } + // The cpu usage value reported on Linux is the average over the process lifetime, + // recalculate the usage over a one second interval + // JSON.stringify is needed to escape spaces, https://github.com/nodejs/node/issues/6803 + let cmd = JSON.stringify(getPathFromAmdModule(require, 'vs/base/node/cpuUsage.sh')); + cmd += ' ' + pids.join(' '); + + exec(cmd, {}, (err, stdout, stderr) => { + if (err || stderr) { + reject(err || new Error(stderr.toString())); + } else { + const cpuUsage = stdout.toString().split('\n'); + for (let i = 0; i < pids.length; i++) { + const processInfo = map.get(pids[i])!; + processInfo.load = parseFloat(cpuUsage[i]); } - // The cpu usage value reported on Linux is the average over the process lifetime, - // recalculate the usage over a one second interval - // JSON.stringify is needed to escape spaces, https://github.com/nodejs/node/issues/6803 - let cmd = JSON.stringify(getPathFromAmdModule(require, 'vs/base/node/cpuUsage.sh')); - cmd += ' ' + pids.join(' '); - - exec(cmd, {}, (err, stdout, stderr) => { - if (err || stderr) { - reject(err || stderr.toString()); - } else { - const cpuUsage = stdout.toString().split('\n'); - for (let i = 0; i < pids.length; i++) { - const processInfo = map.get(pids[i]); - processInfo.load = parseFloat(cpuUsage[i]); - } - - resolve(rootItem); - } - }); - } else { resolve(rootItem); } + }); + } + exec('which ps', {}, (err, stdout, stderr) => { + if (err || stderr) { + if (process.platform !== 'linux') { + reject(err || new Error(stderr.toString())); + } else { + const cmd = JSON.stringify(getPathFromAmdModule(require, 'vs/base/node/ps.sh')); + exec(cmd, {}, (err, stdout, stderr) => { + if (err || stderr) { + reject(err || new Error(stderr.toString())); + } else { + parsePsOutput(stdout, addToTree); + calculateLinuxCpuUsage(); + } + }); + } + } else { + const ps = stdout.toString().trim(); + const args = '-ax -o pid=,ppid=,pcpu=,pmem=,command='; + + // Set numeric locale to ensure '.' is used as the decimal separator + exec(`${ps} ${args}`, { maxBuffer: 1000 * 1024, env: { LC_NUMERIC: 'en_US.UTF-8' } }, (err, stdout, stderr) => { + if (err || stderr) { + reject(err || new Error(stderr.toString())); + } else { + parsePsOutput(stdout, addToTree); + + if (process.platform === 'linux') { + calculateLinuxCpuUsage(); + } else { + resolve(rootItem); + } + } + }); } }); } }); } + +function parsePsOutput(stdout: string, addToTree: (pid: number, ppid: number, cmd: string, load: number, mem: number) => void): void { + const PID_CMD = /^\s*([0-9]+)\s+([0-9]+)\s+([0-9]+\.[0-9]+)\s+([0-9]+\.[0-9]+)\s+(.+)$/; + const lines = stdout.toString().split('\n'); + for (const line of lines) { + const matches = PID_CMD.exec(line.trim()); + if (matches && matches.length === 6) { + addToTree(parseInt(matches[1]), parseInt(matches[2]), matches[5], parseFloat(matches[3]), parseFloat(matches[4])); + } + } +} \ No newline at end of file diff --git a/src/vs/base/node/request.ts b/src/vs/base/node/request.ts deleted file mode 100644 index 0d8d7434f66..00000000000 --- a/src/vs/base/node/request.ts +++ /dev/null @@ -1,183 +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 { isBoolean, isNumber } from 'vs/base/common/types'; -import * as https from 'https'; -import * as http from 'http'; -import { Stream } from 'stream'; -import { parse as parseUrl } from 'url'; -import { createWriteStream } from 'fs'; -import { assign } from 'vs/base/common/objects'; -import { createGunzip } from 'zlib'; -import { CancellationToken } from 'vs/base/common/cancellation'; -import { canceled } from 'vs/base/common/errors'; - -export type Agent = any; - -export interface IRawRequestFunction { - (options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; -} - -export interface IRequestOptions { - type?: string; - url?: string; - user?: string; - password?: string; - headers?: any; - timeout?: number; - data?: string | Stream; - agent?: Agent; - followRedirects?: number; - strictSSL?: boolean; - getRawRequest?(options: IRequestOptions): IRawRequestFunction; -} - -export interface IRequestContext { - // req: http.ClientRequest; - // res: http.ClientResponse; - res: { - headers: { [n: string]: string }; - statusCode?: number; - }; - stream: Stream; -} - -export interface IRequestFunction { - (options: IRequestOptions, token: CancellationToken): Promise; -} - -async function getNodeRequest(options: IRequestOptions): Promise { - const endpoint = parseUrl(options.url!); - const module = endpoint.protocol === 'https:' ? await import('https') : await import('http'); - return module.request; -} - -export function request(options: IRequestOptions, token: CancellationToken): Promise { - let req: http.ClientRequest; - - const rawRequestPromise = options.getRawRequest - ? Promise.resolve(options.getRawRequest(options)) - : Promise.resolve(getNodeRequest(options)); - - return rawRequestPromise.then(rawRequest => { - - return new Promise((c, e) => { - const endpoint = parseUrl(options.url!); - - const opts: https.RequestOptions = { - hostname: endpoint.hostname, - port: endpoint.port ? parseInt(endpoint.port) : (endpoint.protocol === 'https:' ? 443 : 80), - protocol: endpoint.protocol, - path: endpoint.path, - method: options.type || 'GET', - headers: options.headers, - agent: options.agent, - rejectUnauthorized: isBoolean(options.strictSSL) ? options.strictSSL : true - }; - - if (options.user && options.password) { - opts.auth = options.user + ':' + options.password; - } - - req = rawRequest(opts, (res: http.IncomingMessage) => { - const followRedirects: number = isNumber(options.followRedirects) ? options.followRedirects : 3; - if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && followRedirects > 0 && res.headers['location']) { - request(assign({}, options, { - url: res.headers['location'], - followRedirects: followRedirects - 1 - }), token).then(c, e); - } else { - let stream: Stream = res; - - if (res.headers['content-encoding'] === 'gzip') { - stream = stream.pipe(createGunzip()); - } - - c({ res, stream } as IRequestContext); - } - }); - - req.on('error', e); - - if (options.timeout) { - req.setTimeout(options.timeout); - } - - if (options.data) { - if (typeof options.data === 'string') { - req.write(options.data); - } else { - options.data.pipe(req); - return; - } - } - - req.end(); - - token.onCancellationRequested(() => { - req.abort(); - e(canceled()); - }); - }); - }); -} - -function isSuccess(context: IRequestContext): boolean { - return (context.res.statusCode && context.res.statusCode >= 200 && context.res.statusCode < 300) || context.res.statusCode === 1223; -} - -function hasNoContent(context: IRequestContext): boolean { - return context.res.statusCode === 204; -} - -export function download(filePath: string, context: IRequestContext): Promise { - return new Promise((c, e) => { - const out = createWriteStream(filePath); - - out.once('finish', () => c(undefined)); - context.stream.once('error', e); - context.stream.pipe(out); - }); -} - -export function asText(context: IRequestContext): Promise { - return new Promise((c, e) => { - if (!isSuccess(context)) { - return e('Server returned ' + context.res.statusCode); - } - - if (hasNoContent(context)) { - return c(null); - } - - let buffer: string[] = []; - context.stream.on('data', (d: string) => buffer.push(d)); - context.stream.on('end', () => c(buffer.join(''))); - context.stream.on('error', e); - }); -} - -export function asJson(context: IRequestContext): Promise { - return new Promise((c, e) => { - if (!isSuccess(context)) { - return e('Server returned ' + context.res.statusCode); - } - - if (hasNoContent(context)) { - return c(null); - } - - const buffer: string[] = []; - context.stream.on('data', (d: string) => buffer.push(d)); - context.stream.on('end', () => { - try { - c(JSON.parse(buffer.join(''))); - } catch (err) { - e(err); - } - }); - context.stream.on('error', e); - }); -} diff --git a/src/vs/base/node/stats.ts b/src/vs/base/node/stats.ts deleted file mode 100644 index fbf895ea0a6..00000000000 --- a/src/vs/base/node/stats.ts +++ /dev/null @@ -1,198 +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 { readdir, stat, exists, readFile } from 'fs'; -import { join } from 'path'; -import { parse, ParseError } from 'vs/base/common/json'; - -export interface WorkspaceStatItem { - name: string; - count: number; -} - -export interface WorkspaceStats { - fileTypes: WorkspaceStatItem[]; - configFiles: WorkspaceStatItem[]; - fileCount: number; - maxFilesReached: boolean; -} - -function asSortedItems(map: Map): WorkspaceStatItem[] { - let a: WorkspaceStatItem[] = []; - map.forEach((value, index) => a.push({ name: index, count: value })); - return a.sort((a, b) => b.count - a.count); -} - -export function collectLaunchConfigs(folder: string): Promise { - let launchConfigs = new Map(); - - let launchConfig = join(folder, '.vscode', 'launch.json'); - return new Promise((resolve, reject) => { - exists(launchConfig, (doesExist) => { - if (doesExist) { - readFile(launchConfig, (err, contents) => { - if (err) { - return resolve([]); - } - - const errors: ParseError[] = []; - const json = parse(contents.toString(), errors); - if (errors.length) { - console.log(`Unable to parse ${launchConfig}`); - return resolve([]); - } - - if (json['configurations']) { - for (const each of json['configurations']) { - const type = each['type']; - if (type) { - if (launchConfigs.has(type)) { - launchConfigs.set(type, launchConfigs.get(type) + 1); - } - else { - launchConfigs.set(type, 1); - } - } - } - } - - return resolve(asSortedItems(launchConfigs)); - }); - } else { - return resolve([]); - } - }); - }); -} - -export function collectWorkspaceStats(folder: string, filter: string[]): Promise { - const configFilePatterns = [ - { 'tag': 'grunt.js', 'pattern': /^gruntfile\.js$/i }, - { 'tag': 'gulp.js', 'pattern': /^gulpfile\.js$/i }, - { 'tag': 'tsconfig.json', 'pattern': /^tsconfig\.json$/i }, - { 'tag': 'package.json', 'pattern': /^package\.json$/i }, - { 'tag': 'jsconfig.json', 'pattern': /^jsconfig\.json$/i }, - { 'tag': 'tslint.json', 'pattern': /^tslint\.json$/i }, - { 'tag': 'eslint.json', 'pattern': /^eslint\.json$/i }, - { 'tag': 'tasks.json', 'pattern': /^tasks\.json$/i }, - { 'tag': 'launch.json', 'pattern': /^launch\.json$/i }, - { 'tag': 'settings.json', 'pattern': /^settings\.json$/i }, - { 'tag': 'webpack.config.js', 'pattern': /^webpack\.config\.js$/i }, - { 'tag': 'project.json', 'pattern': /^project\.json$/i }, - { 'tag': 'makefile', 'pattern': /^makefile$/i }, - { 'tag': 'sln', 'pattern': /^.+\.sln$/i }, - { 'tag': 'csproj', 'pattern': /^.+\.csproj$/i }, - { 'tag': 'cmake', 'pattern': /^.+\.cmake$/i } - ]; - - let fileTypes = new Map(); - let configFiles = new Map(); - - const MAX_FILES = 20000; - - function walk(dir: string, filter: string[], token, done: (allFiles: string[]) => void): void { - let results: string[] = []; - readdir(dir, async (err, files) => { - // Ignore folders that can't be read - if (err) { - return done(results); - } - - let pending = files.length; - if (pending === 0) { - return done(results); - } - - for (const file of files) { - if (token.maxReached) { - return done(results); - } - - stat(join(dir, file), (err, stats) => { - // Ignore files that can't be read - if (err) { - if (--pending === 0) { - return done(results); - } - } else { - if (stats.isDirectory()) { - if (filter.indexOf(file) === -1) { - walk(join(dir, file), filter, token, (res: string[]) => { - results = results.concat(res); - - if (--pending === 0) { - return done(results); - } - }); - } else { - if (--pending === 0) { - done(results); - } - } - } else { - if (token.count >= MAX_FILES) { - token.maxReached = true; - } - - token.count++; - results.push(file); - - if (--pending === 0) { - done(results); - } - } - } - }); - } - }); - } - - let addFileType = (fileType: string) => { - if (fileTypes.has(fileType)) { - fileTypes.set(fileType, fileTypes.get(fileType) + 1); - } - else { - fileTypes.set(fileType, 1); - } - }; - - let addConfigFiles = (fileName: string) => { - for (const each of configFilePatterns) { - if (each.pattern.test(fileName)) { - if (configFiles.has(each.tag)) { - configFiles.set(each.tag, configFiles.get(each.tag) + 1); - } else { - configFiles.set(each.tag, 1); - } - } - } - }; - - let acceptFile = (name: string) => { - if (name.lastIndexOf('.') >= 0) { - let suffix: string | undefined = name.split('.').pop(); - if (suffix) { - addFileType(suffix); - } - } - addConfigFiles(name); - }; - - let token: { count: number, maxReached: boolean } = { count: 0, maxReached: false }; - - return new Promise((resolve, reject) => { - walk(folder, filter, token, (files) => { - files.forEach(acceptFile); - - resolve({ - configFiles: asSortedItems(configFiles), - fileTypes: asSortedItems(fileTypes), - fileCount: token.count, - maxFilesReached: token.maxReached - - }); - }); - }); -} \ No newline at end of file diff --git a/src/vs/base/node/storage.ts b/src/vs/base/node/storage.ts deleted file mode 100644 index c93e0fea8ab..00000000000 --- a/src/vs/base/node/storage.ts +++ /dev/null @@ -1,695 +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 { Database, Statement } from 'vscode-sqlite3'; -import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; -import { Emitter, Event } from 'vs/base/common/event'; -import { ThrottledDelayer, timeout } from 'vs/base/common/async'; -import { isUndefinedOrNull } from 'vs/base/common/types'; -import { mapToString, setToString } from 'vs/base/common/map'; -import { basename } from 'path'; -import { mark } from 'vs/base/common/performance'; -import { rename, unlinkIgnoreError, copy, renameIgnoreError } from 'vs/base/node/pfs'; - -export enum StorageHint { - - // A hint to the storage that the storage - // does not exist on disk yet. This allows - // the storage library to improve startup - // time by not checking the storage for data. - STORAGE_DOES_NOT_EXIST -} - -export interface IStorageOptions { - hint?: StorageHint; -} - -export interface IUpdateRequest { - insert?: Map; - delete?: Set; -} - -export interface IStorageItemsChangeEvent { - items: Map; -} - -export interface IStorageDatabase { - - readonly onDidChangeItemsExternal: Event; - - getItems(): Promise>; - updateItems(request: IUpdateRequest): Promise; - - close(): Promise; - - checkIntegrity(full: boolean): Promise; -} - -export interface IStorage extends IDisposable { - - readonly items: Map; - readonly size: number; - readonly onDidChangeStorage: Event; - - init(): Promise; - - get(key: string, fallbackValue: string): string; - get(key: string, fallbackValue?: string): string | undefined; - - getBoolean(key: string, fallbackValue: boolean): boolean; - getBoolean(key: string, fallbackValue?: boolean): boolean | undefined; - - getInteger(key: string, fallbackValue: number): number; - getInteger(key: string, fallbackValue?: number): number | undefined; - - set(key: string, value: any): Promise; - delete(key: string): Promise; - - close(): Promise; - - checkIntegrity(full: boolean): Promise; -} - -enum StorageState { - None, - Initialized, - Closed -} - -export class Storage extends Disposable implements IStorage { - _serviceBrand: any; - - private static readonly DEFAULT_FLUSH_DELAY = 100; - - private _onDidChangeStorage: Emitter = this._register(new Emitter()); - get onDidChangeStorage(): Event { return this._onDidChangeStorage.event; } - - private state = StorageState.None; - - private cache: Map = new Map(); - - private flushDelayer: ThrottledDelayer; - - private pendingDeletes: Set = new Set(); - private pendingInserts: Map = new Map(); - - constructor( - protected database: IStorageDatabase, - private options: IStorageOptions = Object.create(null) - ) { - super(); - - this.flushDelayer = this._register(new ThrottledDelayer(Storage.DEFAULT_FLUSH_DELAY)); - - this.registerListeners(); - } - - private registerListeners(): void { - this._register(this.database.onDidChangeItemsExternal(e => this.onDidChangeItemsExternal(e))); - } - - private onDidChangeItemsExternal(e: IStorageItemsChangeEvent): void { - // items that change external require us to update our - // caches with the values. we just accept the value and - // emit an event if there is a change. - e.items.forEach((value, key) => this.accept(key, value)); - } - - private accept(key: string, value: string): void { - if (this.state === StorageState.Closed) { - return; // Return early if we are already closed - } - - let changed = false; - - // Item got removed, check for deletion - if (isUndefinedOrNull(value)) { - changed = this.cache.delete(key); - } - - // Item got updated, check for change - else { - const currentValue = this.cache.get(key); - if (currentValue !== value) { - this.cache.set(key, value); - changed = true; - } - } - - // Signal to outside listeners - if (changed) { - this._onDidChangeStorage.fire(key); - } - } - - get items(): Map { - return this.cache; - } - - get size(): number { - return this.cache.size; - } - - init(): Promise { - if (this.state !== StorageState.None) { - return Promise.resolve(); // either closed or already initialized - } - - this.state = StorageState.Initialized; - - if (this.options.hint === StorageHint.STORAGE_DOES_NOT_EXIST) { - // return early if we know the storage file does not exist. this is a performance - // optimization to not load all items of the underlying storage if we know that - // there can be no items because the storage does not exist. - return Promise.resolve(); - } - - return this.database.getItems().then(items => { - this.cache = items; - }); - } - - get(key: string, fallbackValue: string): string; - get(key: string, fallbackValue?: string): string | undefined; - get(key: string, fallbackValue?: string): string | undefined { - const value = this.cache.get(key); - - if (isUndefinedOrNull(value)) { - return fallbackValue; - } - - return value; - } - - getBoolean(key: string, fallbackValue: boolean): boolean; - getBoolean(key: string, fallbackValue?: boolean): boolean | undefined; - getBoolean(key: string, fallbackValue?: boolean): boolean | undefined { - const value = this.get(key); - - if (isUndefinedOrNull(value)) { - return fallbackValue; - } - - return value === 'true'; - } - - getInteger(key: string, fallbackValue: number): number; - getInteger(key: string, fallbackValue?: number): number | undefined; - getInteger(key: string, fallbackValue?: number): number | undefined { - const value = this.get(key); - - if (isUndefinedOrNull(value)) { - return fallbackValue; - } - - return parseInt(value, 10); - } - - set(key: string, value: any): Promise { - if (this.state === StorageState.Closed) { - return Promise.resolve(); // Return early if we are already closed - } - - // We remove the key for undefined/null values - if (isUndefinedOrNull(value)) { - return this.delete(key); - } - - // Otherwise, convert to String and store - const valueStr = String(value); - - // Return early if value already set - const currentValue = this.cache.get(key); - if (currentValue === valueStr) { - return Promise.resolve(); - } - - // Update in cache and pending - this.cache.set(key, valueStr); - this.pendingInserts.set(key, valueStr); - this.pendingDeletes.delete(key); - - // Event - this._onDidChangeStorage.fire(key); - - // Accumulate work by scheduling after timeout - return this.flushDelayer.trigger(() => this.flushPending()); - } - - delete(key: string): Promise { - if (this.state === StorageState.Closed) { - return Promise.resolve(); // Return early if we are already closed - } - - // Remove from cache and add to pending - const wasDeleted = this.cache.delete(key); - if (!wasDeleted) { - return Promise.resolve(); // Return early if value already deleted - } - - if (!this.pendingDeletes.has(key)) { - this.pendingDeletes.add(key); - } - - this.pendingInserts.delete(key); - - // Event - this._onDidChangeStorage.fire(key); - - // Accumulate work by scheduling after timeout - return this.flushDelayer.trigger(() => this.flushPending()); - } - - close(): Promise { - if (this.state === StorageState.Closed) { - return Promise.resolve(); // return if already closed - } - - // Update state - this.state = StorageState.Closed; - - // Trigger new flush to ensure data is persisted and then close - // even if there is an error flushing. We must always ensure - // the DB is closed to avoid corruption. - const onDone = () => this.database.close(); - return this.flushDelayer.trigger(() => this.flushPending(), 0 /* as soon as possible */).then(onDone, onDone); - } - - private flushPending(): Promise { - if (this.pendingInserts.size === 0 && this.pendingDeletes.size === 0) { - return Promise.resolve(); // return early if nothing to do - } - - // Get pending data - const updateRequest: IUpdateRequest = { insert: this.pendingInserts, delete: this.pendingDeletes }; - - // Reset pending data for next run - this.pendingDeletes = new Set(); - this.pendingInserts = new Map(); - - // Update in storage - return this.database.updateItems(updateRequest); - } - - checkIntegrity(full: boolean): Promise { - return this.database.checkIntegrity(full); - } -} - -interface IOpenDatabaseResult { - db: Database; - path: string; -} - -export interface ISQLiteStorageDatabaseOptions { - logging?: ISQLiteStorageDatabaseLoggingOptions; -} - -export interface ISQLiteStorageDatabaseLoggingOptions { - logError?: (error: string | Error) => void; - logTrace?: (msg: string) => void; -} - -export class SQLiteStorageDatabase implements IStorageDatabase { - - static IN_MEMORY_PATH = ':memory:'; - - get onDidChangeItemsExternal(): Event { return Event.None; } // since we are the only client, there can be no external changes - - private static measuredRequireDuration: boolean; // TODO@Ben remove me after a while - - private static BUSY_OPEN_TIMEOUT = 2000; // timeout in ms to retry when opening DB fails with SQLITE_BUSY - - private name: string; - private logger: SQLiteStorageDatabaseLogger; - - private whenOpened: Promise; - - constructor(path: string, options: ISQLiteStorageDatabaseOptions = Object.create(null)) { - this.name = basename(path); - this.logger = new SQLiteStorageDatabaseLogger(options.logging); - - this.whenOpened = this.open(path); - } - - getItems(): Promise> { - return this.whenOpened.then(({ db }) => { - const items = new Map(); - - return this.all(db, 'SELECT * FROM ItemTable').then(rows => { - rows.forEach(row => items.set(row.key, row.value)); - - if (this.logger.isTracing) { - this.logger.trace(`[storage ${this.name}] getItems(): ${mapToString(items)}`); - } - - return items; - }); - }); - } - - updateItems(request: IUpdateRequest): Promise { - let updateCount = 0; - if (request.insert) { - updateCount += request.insert.size; - } - if (request.delete) { - updateCount += request.delete.size; - } - - if (updateCount === 0) { - return Promise.resolve(); - } - - if (this.logger.isTracing) { - this.logger.trace(`[storage ${this.name}] updateItems(): insert(${request.insert ? mapToString(request.insert) : '0'}), delete(${request.delete ? setToString(request.delete) : '0'})`); - } - - return this.whenOpened.then(({ db }) => { - return this.transaction(db, () => { - if (request.insert && request.insert.size > 0) { - this.prepare(db, 'INSERT INTO ItemTable VALUES (?,?)', stmt => { - request.insert!.forEach((value, key) => { - stmt.run([key, value]); - }); - }); - } - - if (request.delete && request.delete.size) { - this.prepare(db, 'DELETE FROM ItemTable WHERE key=?', stmt => { - request.delete!.forEach(key => { - stmt.run(key); - }); - }); - } - }); - }); - } - - close(): Promise { - this.logger.trace(`[storage ${this.name}] close()`); - - return this.whenOpened.then(result => { - return new Promise((resolve, reject) => { - result.db.close(error => { - if (error) { - this.logger.error(`[storage ${this.name}] close(): ${error}`); - - return reject(error); - } - - // If the DB closed successfully and we are not running in-memory - // make a backup of the DB so that we can use it as fallback in - // case the actual DB becomes corrupt. - if (result.path !== SQLiteStorageDatabase.IN_MEMORY_PATH) { - return this.backup(result).then(resolve, error => { - this.logger.error(`[storage ${this.name}] backup(): ${error}`); - - return resolve(); // ignore failing backup - }); - } - - return resolve(); - }); - }); - }); - } - - private backup(db: IOpenDatabaseResult): Promise { - if (db.path === SQLiteStorageDatabase.IN_MEMORY_PATH) { - return Promise.resolve(); // no backups when running in-memory - } - - const backupPath = this.toBackupPath(db.path); - - return unlinkIgnoreError(backupPath).then(() => copy(db.path, backupPath)); - } - - private toBackupPath(path: string): string { - return `${path}.backup`; - } - - checkIntegrity(full: boolean): Promise { - this.logger.trace(`[storage ${this.name}] checkIntegrity(full: ${full})`); - - return this.whenOpened.then(({ db }) => { - return this.get(db, full ? 'PRAGMA integrity_check' : 'PRAGMA quick_check').then(row => { - return full ? row['integrity_check'] : row['quick_check']; - }); - }); - } - - private open(path: string): Promise { - this.logger.trace(`[storage ${this.name}] open()`); - - return new Promise((resolve, reject) => { - const fallbackToInMemoryDatabase = (error: Error) => { - this.logger.error(`[storage ${this.name}] open(): Error (open DB): ${error}`); - this.logger.error(`[storage ${this.name}] open(): Falling back to in-memory DB`); - - // In case of any error to open the DB, use an in-memory - // DB so that we always have a valid DB to talk to. - this.doOpen(SQLiteStorageDatabase.IN_MEMORY_PATH).then(resolve, reject); - }; - - this.doOpen(path).then(resolve, error => { - - // This error code should only arise if another process is locking the same DB we - // want to open at that time. This typically never happens because a DB connection - // is limited per window. However, in the event of a window reload, it may be possible - // that the previous connection was not properly closed while the new connection is - // already established. - if (error.code === 'SQLITE_BUSY') { - return this.handleSQLiteBusy(path).then(resolve, fallbackToInMemoryDatabase); - } - - // This error code indicates that even though the DB file exists, - // SQLite cannot open it and signals it is corrupt or not a DB. - if (error.code === 'SQLITE_CORRUPT' || error.code === 'SQLITE_NOTADB') { - return this.handleSQLiteCorrupt(path, error).then(resolve, fallbackToInMemoryDatabase); - } - - // Otherwise give up and fallback to in-memory DB - return fallbackToInMemoryDatabase(error); - }); - }); - } - - private handleSQLiteBusy(path: string): Promise { - this.logger.error(`[storage ${this.name}] open(): Retrying after ${SQLiteStorageDatabase.BUSY_OPEN_TIMEOUT}ms due to SQLITE_BUSY`); - - // Retry after some time if the DB is busy - return timeout(SQLiteStorageDatabase.BUSY_OPEN_TIMEOUT).then(() => this.doOpen(path)); - } - - private handleSQLiteCorrupt(path: string, error: any): Promise { - this.logger.error(`[storage ${this.name}] open(): Unable to open DB due to ${error.code}`); - - // Move corrupt DB to a different filename and try to load from backup - // If that fails, a new empty DB is being created automatically - return rename(path, this.toCorruptPath(path)) - .then(() => renameIgnoreError(this.toBackupPath(path), path)) - .then(() => this.doOpen(path)); - } - - private toCorruptPath(path: string): string { - const randomSuffix = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 4); - - return `${path}.${randomSuffix}.corrupt`; - } - - private doOpen(path: string): Promise { - // TODO@Ben clean up performance markers - return new Promise((resolve, reject) => { - let measureRequireDuration = false; - if (!SQLiteStorageDatabase.measuredRequireDuration) { - SQLiteStorageDatabase.measuredRequireDuration = true; - measureRequireDuration = true; - - mark('willRequireSQLite'); - } - import('vscode-sqlite3').then(sqlite3 => { - if (measureRequireDuration) { - mark('didRequireSQLite'); - } - - const db: Database = new (this.logger.isTracing ? sqlite3.verbose().Database : sqlite3.Database)(path, error => { - if (error) { - return db ? db.close(() => reject(error)) : reject(error); - } - - // The following exec() statement serves two purposes: - // - create the DB if it does not exist yet - // - validate that the DB is not corrupt (the open() call does not throw otherwise) - mark('willSetupSQLiteSchema'); - this.exec(db, [ - 'PRAGMA user_version = 1;', - 'CREATE TABLE IF NOT EXISTS ItemTable (key TEXT UNIQUE ON CONFLICT REPLACE, value BLOB)' - ].join('')).then(() => { - mark('didSetupSQLiteSchema'); - - return resolve({ path, db }); - }, error => { - mark('didSetupSQLiteSchema'); - - return db.close(() => reject(error)); - }); - }); - - // Errors - db.on('error', error => this.logger.error(`[storage ${this.name}] Error (event): ${error}`)); - - // Tracing - if (this.logger.isTracing) { - db.on('trace', sql => this.logger.trace(`[storage ${this.name}] Trace (event): ${sql}`)); - } - }); - }); - } - - private exec(db: Database, sql: string): Promise { - return new Promise((resolve, reject) => { - db.exec(sql, error => { - if (error) { - this.logger.error(`[storage ${this.name}] exec(): ${error}`); - - return reject(error); - } - - return resolve(); - }); - }); - } - - private get(db: Database, sql: string): Promise { - return new Promise((resolve, reject) => { - db.get(sql, (error, row) => { - if (error) { - this.logger.error(`[storage ${this.name}] get(): ${error}`); - - return reject(error); - } - - return resolve(row); - }); - }); - } - - private all(db: Database, sql: string): Promise<{ key: string, value: string }[]> { - return new Promise((resolve, reject) => { - db.all(sql, (error, rows) => { - if (error) { - this.logger.error(`[storage ${this.name}] all(): ${error}`); - - return reject(error); - } - - return resolve(rows); - }); - }); - } - - private transaction(db: Database, transactions: () => void): Promise { - return new Promise((resolve, reject) => { - db.serialize(() => { - db.run('BEGIN TRANSACTION'); - - transactions(); - - db.run('END TRANSACTION', error => { - if (error) { - this.logger.error(`[storage ${this.name}] transaction(): ${error}`); - - return reject(error); - } - - return resolve(); - }); - }); - }); - } - - private prepare(db: Database, sql: string, runCallback: (stmt: Statement) => void): void { - const stmt = db.prepare(sql); - - const statementErrorListener = error => { - this.logger.error(`[storage ${this.name}] prepare(): ${error} (${sql})`); - }; - - stmt.on('error', statementErrorListener); - - runCallback(stmt); - - stmt.finalize(error => { - if (error) { - statementErrorListener(error); - } - - stmt.removeListener('error', statementErrorListener); - }); - } -} - -class SQLiteStorageDatabaseLogger { - private readonly logTrace: (msg: string) => void; - private readonly logError: (error: string | Error) => void; - - constructor(options?: ISQLiteStorageDatabaseLoggingOptions) { - if (options && typeof options.logTrace === 'function') { - this.logTrace = options.logTrace; - } - - if (options && typeof options.logError === 'function') { - this.logError = options.logError; - } - } - - get isTracing(): boolean { - return !!this.logTrace; - } - - trace(msg: string): void { - if (this.logTrace) { - this.logTrace(msg); - } - } - - error(error: string | Error): void { - if (this.logError) { - this.logError(error); - } - } -} - -export class InMemoryStorageDatabase implements IStorageDatabase { - - readonly onDidChangeItemsExternal = Event.None; - - private items = new Map(); - - getItems(): Promise> { - return Promise.resolve(this.items); - } - - updateItems(request: IUpdateRequest): Promise { - if (request.insert) { - request.insert.forEach((value, key) => this.items.set(key, value)); - } - - if (request.delete) { - request.delete.forEach(key => this.items.delete(key)); - } - - return Promise.resolve(); - } - - close(): Promise { - return Promise.resolve(); - } - - checkIntegrity(full: boolean): Promise { - return Promise.resolve('ok'); - } -} \ No newline at end of file diff --git a/src/vs/base/node/stream.ts b/src/vs/base/node/stream.ts index 845afdab8e9..16b73835bd1 100644 --- a/src/vs/base/node/stream.ts +++ b/src/vs/base/node/stream.ts @@ -4,63 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as fs from 'fs'; - -export interface ReadResult { - buffer: Buffer | null; - bytesRead: number; -} - -/** - * Reads totalBytes from the provided file. - */ -export function readExactlyByFile(file: string, totalBytes: number): Promise { - return new Promise((resolve, reject) => { - fs.open(file, 'r', null, (err, fd) => { - if (err) { - return reject(err); - } - - function end(err: Error | null, resultBuffer: Buffer | null, bytesRead: number): void { - fs.close(fd, closeError => { - if (closeError) { - return reject(closeError); - } - - if (err && (err).code === 'EISDIR') { - return reject(err); // we want to bubble this error up (file is actually a folder) - } - - return resolve({ buffer: resultBuffer, bytesRead }); - }); - } - - const buffer = Buffer.allocUnsafe(totalBytes); - let offset = 0; - - function readChunk(): void { - fs.read(fd, buffer, offset, totalBytes - offset, null, (err, bytesRead) => { - if (err) { - return end(err, null, 0); - } - - if (bytesRead === 0) { - return end(null, buffer, offset); - } - - offset += bytesRead; - - if (offset === totalBytes) { - return end(null, buffer, offset); - } - - return readChunk(); - }); - } - - readChunk(); - }); - }); -} +import { VSBufferReadableStream, VSBufferReadable, VSBuffer } from 'vs/base/common/buffer'; +import { Readable } from 'stream'; +import { isUndefinedOrNull } from 'vs/base/common/types'; +import { UTF8, UTF8_with_bom, UTF8_BOM, UTF16be, UTF16le_BOM, UTF16be_BOM, UTF16le, UTF_ENCODING } from 'vs/base/node/encoding'; /** * Reads a file until a matching string is found. @@ -92,7 +39,7 @@ export function readToMatchingString(file: string, matchingString: string, chunk }); } - let buffer = Buffer.allocUnsafe(maximumBytesToRead); + const buffer = Buffer.allocUnsafe(maximumBytesToRead); let offset = 0; function readChunk(): void { @@ -123,4 +70,107 @@ export function readToMatchingString(file: string, matchingString: string, chunk readChunk(); }) ); -} \ No newline at end of file +} + +export function streamToNodeReadable(stream: VSBufferReadableStream): Readable { + return new class extends Readable { + private listening = false; + + _read(size?: number): void { + if (!this.listening) { + this.listening = true; + + // Data + stream.on('data', data => { + try { + if (!this.push(data.buffer)) { + stream.pause(); // pause the stream if we should not push anymore + } + } catch (error) { + this.emit(error); + } + }); + + // End + stream.on('end', () => { + try { + this.push(null); // signal EOS + } catch (error) { + this.emit(error); + } + }); + + // Error + stream.on('error', error => this.emit('error', error)); + } + + // ensure the stream is flowing + stream.resume(); + } + + _destroy(error: Error | null, callback: (error: Error | null) => void): void { + stream.destroy(); + + callback(null); + } + }; +} + +export function nodeReadableToString(stream: NodeJS.ReadableStream): Promise { + return new Promise((resolve, reject) => { + let result = ''; + + stream.on('data', chunk => result += chunk); + stream.on('error', reject); + stream.on('end', () => resolve(result)); + }); +} + +export function nodeStreamToVSBufferReadable(stream: NodeJS.ReadWriteStream, addBOM?: { encoding: UTF_ENCODING }): VSBufferReadable { + let bytesRead = 0; + let done = false; + + return { + read(): VSBuffer | null { + if (done) { + return null; + } + + const res = stream.read(); + if (isUndefinedOrNull(res)) { + done = true; + + // If we are instructed to add a BOM but we detect that no + // bytes have been read, we must ensure to return the BOM + // ourselves so that we comply with the contract. + if (bytesRead === 0 && addBOM) { + switch (addBOM.encoding) { + case UTF8: + case UTF8_with_bom: + return VSBuffer.wrap(Buffer.from(UTF8_BOM)); + case UTF16be: + return VSBuffer.wrap(Buffer.from(UTF16be_BOM)); + case UTF16le: + return VSBuffer.wrap(Buffer.from(UTF16le_BOM)); + } + } + + return null; + } + + // Handle String + if (typeof res === 'string') { + bytesRead += res.length; + + return VSBuffer.fromString(res); + } + + // Handle Buffer + else { + bytesRead += res.byteLength; + + return VSBuffer.wrap(res); + } + } + }; +} diff --git a/src/vs/platform/node/test/fixtures/extract.zip b/src/vs/base/node/test/fixtures/extract.zip similarity index 100% rename from src/vs/platform/node/test/fixtures/extract.zip rename to src/vs/base/node/test/fixtures/extract.zip diff --git a/src/vs/platform/node/test/zip.test.ts b/src/vs/base/node/test/zip.test.ts similarity index 86% rename from src/vs/platform/node/test/zip.test.ts rename to src/vs/base/node/test/zip.test.ts index cec3c261038..f79bddaa98c 100644 --- a/src/vs/platform/node/test/zip.test.ts +++ b/src/vs/base/node/test/zip.test.ts @@ -4,12 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import * as path from 'path'; +import * as path from 'vs/base/common/path'; import * as os from 'os'; -import { extract } from 'vs/platform/node/zip'; +import { extract } from 'vs/base/node/zip'; import { generateUuid } from 'vs/base/common/uuid'; import { rimraf, exists } from 'vs/base/node/pfs'; -import { NullLogService } from 'vs/platform/log/common/log'; import { getPathFromAmdModule } from 'vs/base/common/amd'; import { createCancelablePromise } from 'vs/base/common/async'; @@ -21,7 +20,7 @@ suite('Zip', () => { const fixture = path.join(fixtures, 'extract.zip'); const target = path.join(os.tmpdir(), generateUuid()); - return createCancelablePromise(token => extract(fixture, target, {}, new NullLogService(), token) + return createCancelablePromise(token => extract(fixture, target, {}, token) .then(() => exists(path.join(target, 'extension'))) .then(exists => assert(exists)) .then(() => rimraf(target))); diff --git a/src/vs/base/node/watcher.ts b/src/vs/base/node/watcher.ts new file mode 100644 index 00000000000..b51f73c6eaa --- /dev/null +++ b/src/vs/base/node/watcher.ts @@ -0,0 +1,192 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { join, basename } from 'vs/base/common/path'; +import { watch } from 'fs'; +import { isMacintosh } from 'vs/base/common/platform'; +import { normalizeNFC } from 'vs/base/common/normalization'; +import { toDisposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { exists, readdir } from 'vs/base/node/pfs'; + +export function watchFile(path: string, onChange: (type: 'changed' | 'deleted', path: string) => void, onError: (error: string) => void): IDisposable { + return doWatchNonRecursive({ path, isDirectory: false }, onChange, onError); +} + +export function watchFolder(path: string, onChange: (type: 'added' | 'changed' | 'deleted', path: string) => void, onError: (error: string) => void): IDisposable { + return doWatchNonRecursive({ path, isDirectory: true }, onChange, onError); +} + +export const CHANGE_BUFFER_DELAY = 100; + +function doWatchNonRecursive(file: { path: string, isDirectory: boolean }, onChange: (type: 'added' | 'changed' | 'deleted', path: string) => void, onError: (error: string) => void): IDisposable { + const originalFileName = basename(file.path); + const mapPathToStatDisposable = new Map(); + + let disposed = false; + let watcherDisposables: IDisposable[] = [toDisposable(() => { + mapPathToStatDisposable.forEach(disposable => dispose(disposable)); + mapPathToStatDisposable.clear(); + })]; + + try { + + // Creating watcher can fail with an exception + const watcher = watch(file.path); + watcherDisposables.push(toDisposable(() => { + watcher.removeAllListeners(); + watcher.close(); + })); + + // Folder: resolve children to emit proper events + const folderChildren: Set = new Set(); + if (file.isDirectory) { + readdir(file.path).then(children => children.forEach(child => folderChildren.add(child))); + } + + watcher.on('error', (code: number, signal: string) => { + if (!disposed) { + onError(`Failed to watch ${file.path} for changes using fs.watch() (${code}, ${signal})`); + } + }); + + watcher.on('change', (type, raw) => { + if (disposed) { + return; // ignore if already disposed + } + + // Normalize file name + let changedFileName: string = ''; + if (raw) { // https://github.com/Microsoft/vscode/issues/38191 + changedFileName = raw.toString(); + if (isMacintosh) { + // Mac: uses NFD unicode form on disk, but we want NFC + // See also https://github.com/nodejs/node/issues/2165 + changedFileName = normalizeNFC(changedFileName); + } + } + + if (!changedFileName || (type !== 'change' && type !== 'rename')) { + return; // ignore unexpected events + } + + // File path: use path directly for files and join with changed file name otherwise + const changedFilePath = file.isDirectory ? join(file.path, changedFileName) : file.path; + + // File + if (!file.isDirectory) { + if (type === 'rename' || changedFileName !== originalFileName) { + // The file was either deleted or renamed. Many tools apply changes to files in an + // atomic way ("Atomic Save") by first renaming the file to a temporary name and then + // renaming it back to the original name. Our watcher will detect this as a rename + // and then stops to work on Mac and Linux because the watcher is applied to the + // inode and not the name. The fix is to detect this case and trying to watch the file + // again after a certain delay. + // In addition, we send out a delete event if after a timeout we detect that the file + // does indeed not exist anymore. + + const timeoutHandle = setTimeout(async () => { + const fileExists = await exists(changedFilePath); + + if (disposed) { + return; // ignore if disposed by now + } + + // File still exists, so emit as change event and reapply the watcher + if (fileExists) { + onChange('changed', changedFilePath); + + watcherDisposables = [doWatchNonRecursive(file, onChange, onError)]; + } + + // File seems to be really gone, so emit a deleted event + else { + onChange('deleted', changedFilePath); + } + }, CHANGE_BUFFER_DELAY); + + // Very important to dispose the watcher which now points to a stale inode + // and wire in a new disposable that tracks our timeout that is installed + dispose(watcherDisposables); + watcherDisposables = [toDisposable(() => clearTimeout(timeoutHandle))]; + } else { + onChange('changed', changedFilePath); + } + } + + // Folder + else { + + // Children add/delete + if (type === 'rename') { + + // Cancel any previous stats for this file path if existing + const statDisposable = mapPathToStatDisposable.get(changedFilePath); + if (statDisposable) { + dispose(statDisposable); + } + + // Wait a bit and try see if the file still exists on disk to decide on the resulting event + const timeoutHandle = setTimeout(async () => { + mapPathToStatDisposable.delete(changedFilePath); + + const fileExists = await exists(changedFilePath); + + if (disposed) { + return; // ignore if disposed by now + } + + // Figure out the correct event type: + // File Exists: either 'added' or 'changed' if known before + // File Does not Exist: always 'deleted' + let type: 'added' | 'deleted' | 'changed'; + if (fileExists) { + if (folderChildren.has(changedFileName)) { + type = 'changed'; + } else { + type = 'added'; + folderChildren.add(changedFileName); + } + } else { + folderChildren.delete(changedFileName); + type = 'deleted'; + } + + onChange(type, changedFilePath); + }, CHANGE_BUFFER_DELAY); + + mapPathToStatDisposable.set(changedFilePath, toDisposable(() => clearTimeout(timeoutHandle))); + } + + // Other events + else { + + // Figure out the correct event type: if this is the + // first time we see this child, it can only be added + let type: 'added' | 'changed'; + if (folderChildren.has(changedFileName)) { + type = 'changed'; + } else { + type = 'added'; + folderChildren.add(changedFileName); + } + + onChange(type, changedFilePath); + } + } + }); + } catch (error) { + exists(file.path).then(exists => { + if (exists && !disposed) { + onError(`Failed to watch ${file.path} for changes using fs.watch() (${error.toString()})`); + } + }); + } + + return toDisposable(() => { + disposed = true; + + watcherDisposables = dispose(watcherDisposables); + }); +} \ No newline at end of file diff --git a/src/vs/platform/node/zip.ts b/src/vs/base/node/zip.ts similarity index 85% rename from src/vs/platform/node/zip.ts rename to src/vs/base/node/zip.ts index be8629a236a..3c474dc0343 100644 --- a/src/vs/platform/node/zip.ts +++ b/src/vs/base/node/zip.ts @@ -4,14 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import * as path from 'path'; +import * as path from 'vs/base/common/path'; import { createWriteStream, WriteStream } from 'fs'; import { Readable } from 'stream'; -import { nfcall, ninvoke, Sequencer, createCancelablePromise } from 'vs/base/common/async'; +import { Sequencer, createCancelablePromise } from 'vs/base/common/async'; import { mkdirp, rimraf } from 'vs/base/node/pfs'; import { open as _openZip, Entry, ZipFile } from 'yauzl'; import * as yazl from 'yazl'; -import { ILogService } from 'vs/platform/log/common/log'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Event } from 'vs/base/common/event'; @@ -50,7 +49,7 @@ export class ExtractError extends Error { } function modeFromEntry(entry: Entry) { - let attr = entry.externalFileAttributes >> 16 || 33188; + const attr = entry.externalFileAttributes >> 16 || 33188; return [448 /* S_IRWXU */, 56 /* S_IRWXG */, 7 /* S_IRWXO */] .map(mask => attr & mask) @@ -87,7 +86,7 @@ function extractEntry(stream: Readable, fileName: string, mode: number, targetPa } }); - return Promise.resolve(mkdirp(targetDirName, undefined, token)).then(() => new Promise((c, e) => { + return Promise.resolve(mkdirp(targetDirName, undefined, token)).then(() => new Promise((c, e) => { if (token.isCancellationRequested) { return; } @@ -104,12 +103,11 @@ function extractEntry(stream: Readable, fileName: string, mode: number, targetPa })); } -function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions, logService: ILogService, token: CancellationToken): Promise { +function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions, token: CancellationToken): Promise { let last = createCancelablePromise(() => Promise.resolve()); let extractedEntriesCount = 0; Event.once(token.onCancellationRequested)(() => { - logService.debug(targetPath, 'Cancelled.'); last.cancel(); zipfile.close(); }); @@ -155,7 +153,7 @@ function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions, log return; } - const stream = ninvoke(zipfile, zipfile.openReadStream, entry); + const stream = openZipStream(zipfile, entry); const mode = modeFromEntry(entry); last = createCancelablePromise(token => throttler.queue(() => stream.then(stream => extractEntry(stream, fileName, mode, targetPath, options, token).then(() => readNextEntry(token)))).then(null!, e)); @@ -164,8 +162,27 @@ function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions, log } function openZip(zipFile: string, lazy: boolean = false): Promise { - return nfcall(_openZip, zipFile, lazy ? { lazyEntries: true } : undefined) - .then(undefined, err => Promise.reject(toExtractError(err))); + return new Promise((resolve, reject) => { + _openZip(zipFile, lazy ? { lazyEntries: true } : undefined, (error?: Error, zipfile?: ZipFile) => { + if (error) { + reject(toExtractError(error)); + } else { + resolve(zipfile); + } + }); + }); +} + +function openZipStream(zipFile: ZipFile, entry: Entry): Promise { + return new Promise((resolve, reject) => { + zipFile.openReadStream(entry, (error?: Error, stream?: Readable) => { + if (error) { + reject(toExtractError(error)); + } else { + resolve(stream); + } + }); + }); } export interface IFile { @@ -195,7 +212,7 @@ export function zip(zipPath: string, files: IFile[]): Promise { }); } -export function extract(zipPath: string, targetPath: string, options: IExtractOptions = {}, logService: ILogService, token: CancellationToken): Promise { +export function extract(zipPath: string, targetPath: string, options: IExtractOptions = {}, token: CancellationToken): Promise { const sourcePathRegex = new RegExp(options.sourcePath ? `^${options.sourcePath}` : ''); let promise = openZip(zipPath, true); @@ -204,7 +221,7 @@ export function extract(zipPath: string, targetPath: string, options: IExtractOp promise = promise.then(zipfile => rimraf(targetPath).then(() => zipfile)); } - return promise.then(zipfile => extractZip(zipfile, targetPath, { sourcePathRegex }, logService, token)); + return promise.then(zipfile => extractZip(zipfile, targetPath, { sourcePathRegex }, token)); } function read(zipPath: string, filePath: string): Promise { @@ -212,7 +229,7 @@ function read(zipPath: string, filePath: string): Promise { return new Promise((c, e) => { zipfile.on('entry', (entry: Entry) => { if (entry.fileName === filePath) { - ninvoke(zipfile, zipfile.openReadStream, entry).then(stream => c(stream), err => e(err)); + openZipStream(zipfile, entry).then(stream => c(stream), err => e(err)); } }); @@ -226,7 +243,7 @@ export function buffer(zipPath: string, filePath: string): Promise { return new Promise((c, e) => { const buffers: Buffer[] = []; stream.once('error', e); - stream.on('data', b => buffers.push(b as Buffer)); + stream.on('data', (b: Buffer) => buffers.push(b)); stream.on('end', () => c(Buffer.concat(buffers))); }); }); diff --git a/src/vs/base/parts/contextmenu/electron-browser/contextmenu.ts b/src/vs/base/parts/contextmenu/electron-browser/contextmenu.ts index b4f83b7467c..26212a79fe1 100644 --- a/src/vs/base/parts/contextmenu/electron-browser/contextmenu.ts +++ b/src/vs/base/parts/contextmenu/electron-browser/contextmenu.ts @@ -37,7 +37,7 @@ export function popup(items: IContextMenuItem[], options?: IPopupOptions): void } function createItem(item: IContextMenuItem, processedItems: IContextMenuItem[]): ISerializableContextMenuItem { - const serializableItem = { + const serializableItem: ISerializableContextMenuItem = { id: processedItems.length, label: item.label, type: item.type, @@ -45,7 +45,7 @@ function createItem(item: IContextMenuItem, processedItems: IContextMenuItem[]): checked: item.checked, enabled: typeof item.enabled === 'boolean' ? item.enabled : true, visible: typeof item.visible === 'boolean' ? item.visible : true - } as ISerializableContextMenuItem; + }; processedItems.push(item); diff --git a/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts b/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts index fa579321906..f375750dc20 100644 --- a/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts +++ b/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts @@ -16,7 +16,12 @@ export function registerContextMenuListener(): void { y: options ? options.y : undefined, positioningItem: options ? options.positioningItem : undefined, callback: () => { - event.sender.send(CONTEXT_MENU_CLOSE_CHANNEL, contextMenuId); + // Workaround for https://github.com/Microsoft/vscode/issues/72447 + // It turns out that the menu gets GC'ed if not referenced anymore + // As such we drag it into this scope so that it is not being GC'ed + if (menu) { + event.sender.send(CONTEXT_MENU_CLOSE_CHANNEL, contextMenuId); + } } }); }); diff --git a/src/vs/base/parts/ipc/common/ipc.net.ts b/src/vs/base/parts/ipc/common/ipc.net.ts new file mode 100644 index 00000000000..459a5b94bd8 --- /dev/null +++ b/src/vs/base/parts/ipc/common/ipc.net.ts @@ -0,0 +1,813 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event, Emitter } from 'vs/base/common/event'; +import { IMessagePassingProtocol, IPCClient } from 'vs/base/parts/ipc/common/ipc'; +import { IDisposable, Disposable, dispose } from 'vs/base/common/lifecycle'; +import { VSBuffer } from 'vs/base/common/buffer'; +import * as platform from 'vs/base/common/platform'; + +declare var process: any; + +export interface ISocket extends IDisposable { + onData(listener: (e: VSBuffer) => void): IDisposable; + onClose(listener: () => void): IDisposable; + onEnd(listener: () => void): IDisposable; + write(buffer: VSBuffer): void; + end(): void; +} + +let emptyBuffer: VSBuffer | null = null; +function getEmptyBuffer(): VSBuffer { + if (!emptyBuffer) { + emptyBuffer = VSBuffer.alloc(0); + } + return emptyBuffer; +} + +export class ChunkStream { + + private _chunks: VSBuffer[]; + private _totalLength: number; + + public get byteLength() { + return this._totalLength; + } + + constructor() { + this._chunks = []; + this._totalLength = 0; + } + + public acceptChunk(buff: VSBuffer) { + this._chunks.push(buff); + this._totalLength += buff.byteLength; + } + + public read(byteCount: number): VSBuffer { + return this._read(byteCount, true); + } + + public peek(byteCount: number): VSBuffer { + return this._read(byteCount, false); + } + + private _read(byteCount: number, advance: boolean): VSBuffer { + + if (byteCount === 0) { + return getEmptyBuffer(); + } + + if (byteCount > this._totalLength) { + throw new Error(`Cannot read so many bytes!`); + } + + if (this._chunks[0].byteLength === byteCount) { + // super fast path, precisely first chunk must be returned + const result = this._chunks[0]; + if (advance) { + this._chunks.shift(); + this._totalLength -= byteCount; + } + return result; + } + + if (this._chunks[0].byteLength > byteCount) { + // fast path, the reading is entirely within the first chunk + const result = this._chunks[0].slice(0, byteCount); + if (advance) { + this._chunks[0] = this._chunks[0].slice(byteCount); + this._totalLength -= byteCount; + } + return result; + } + + let result = VSBuffer.alloc(byteCount); + let resultOffset = 0; + let chunkIndex = 0; + while (byteCount > 0) { + const chunk = this._chunks[chunkIndex]; + if (chunk.byteLength > byteCount) { + // this chunk will survive + const chunkPart = chunk.slice(0, byteCount); + result.set(chunkPart, resultOffset); + resultOffset += byteCount; + + if (advance) { + this._chunks[chunkIndex] = chunk.slice(byteCount); + this._totalLength -= byteCount; + } + + byteCount -= byteCount; + } else { + // this chunk will be entirely read + result.set(chunk, resultOffset); + resultOffset += chunk.byteLength; + + if (advance) { + this._chunks.shift(); + this._totalLength -= chunk.byteLength; + } else { + chunkIndex++; + } + + byteCount -= chunk.byteLength; + } + } + return result; + } +} + +const enum ProtocolMessageType { + None = 0, + Regular = 1, + Control = 2, + Ack = 3, + KeepAlive = 4, + Disconnect = 5 +} + +export const enum ProtocolConstants { + HeaderLength = 13, + /** + * Send an Acknowledge message at most 2 seconds later... + */ + AcknowledgeTime = 2000, // 2 seconds + /** + * If there is a message that has been unacknowledged for 10 seconds, consider the connection closed... + */ + AcknowledgeTimeoutTime = 10000, // 10 seconds + /** + * Send at least a message every 5s for keep alive reasons. + */ + KeepAliveTime = 5000, // 5 seconds + /** + * If there is no message received for 10 seconds, consider the connection closed... + */ + KeepAliveTimeoutTime = 10000, // 10 seconds + /** + * If there is no reconnection within this time-frame, consider the connection permanently closed... + */ + ReconnectionGraceTime = 3 * 60 * 60 * 1000, // 3hrs +} + +class ProtocolMessage { + + public writtenTime: number; + + constructor( + public readonly type: ProtocolMessageType, + public readonly id: number, + public readonly ack: number, + public readonly data: VSBuffer + ) { + this.writtenTime = 0; + } + + public get size(): number { + return this.data.byteLength; + } +} + +class ProtocolReader extends Disposable { + + private readonly _socket: ISocket; + private _isDisposed: boolean; + private readonly _incomingData: ChunkStream; + public lastReadTime: number; + + private readonly _onMessage = this._register(new Emitter()); + public readonly onMessage: Event = this._onMessage.event; + + private readonly _state = { + readHead: true, + readLen: ProtocolConstants.HeaderLength, + messageType: ProtocolMessageType.None, + id: 0, + ack: 0 + }; + + constructor(socket: ISocket) { + super(); + this._socket = socket; + this._isDisposed = false; + this._incomingData = new ChunkStream(); + this._register(this._socket.onData(data => this.acceptChunk(data))); + this.lastReadTime = Date.now(); + } + + public acceptChunk(data: VSBuffer | null): void { + if (!data || data.byteLength === 0) { + return; + } + + this.lastReadTime = Date.now(); + + this._incomingData.acceptChunk(data); + + while (this._incomingData.byteLength >= this._state.readLen) { + + const buff = this._incomingData.read(this._state.readLen); + + if (this._state.readHead) { + // buff is the header + + // save new state => next time will read the body + this._state.readHead = false; + this._state.readLen = buff.readUInt32BE(9); + this._state.messageType = buff.readUInt8(0); + this._state.id = buff.readUInt32BE(1); + this._state.ack = buff.readUInt32BE(5); + } else { + // buff is the body + const messageType = this._state.messageType; + const id = this._state.id; + const ack = this._state.ack; + + // save new state => next time will read the header + this._state.readHead = true; + this._state.readLen = ProtocolConstants.HeaderLength; + this._state.messageType = ProtocolMessageType.None; + this._state.id = 0; + this._state.ack = 0; + + this._onMessage.fire(new ProtocolMessage(messageType, id, ack, buff)); + + if (this._isDisposed) { + // check if an event listener lead to our disposal + break; + } + } + } + } + + public readEntireBuffer(): VSBuffer { + return this._incomingData.read(this._incomingData.byteLength); + } + + public dispose(): void { + this._isDisposed = true; + super.dispose(); + } +} + +class ProtocolWriter { + + private _isDisposed: boolean; + private readonly _socket: ISocket; + private _data: VSBuffer[]; + private _totalLength: number; + public lastWriteTime: number; + + constructor(socket: ISocket) { + this._isDisposed = false; + this._socket = socket; + this._data = []; + this._totalLength = 0; + this.lastWriteTime = 0; + } + + public dispose(): void { + this.flush(); + this._isDisposed = true; + } + + public flush(): void { + // flush + this._writeNow(); + } + + public write(msg: ProtocolMessage) { + if (this._isDisposed) { + console.warn(`Cannot write message in a disposed ProtocolWriter`); + console.warn(msg); + return; + } + msg.writtenTime = Date.now(); + this.lastWriteTime = Date.now(); + const header = VSBuffer.alloc(ProtocolConstants.HeaderLength); + header.writeUInt8(msg.type, 0); + header.writeUInt32BE(msg.id, 1); + header.writeUInt32BE(msg.ack, 5); + header.writeUInt32BE(msg.data.byteLength, 9); + this._writeSoon(header, msg.data); + } + + private _bufferAdd(head: VSBuffer, body: VSBuffer): boolean { + const wasEmpty = this._totalLength === 0; + this._data.push(head, body); + this._totalLength += head.byteLength + body.byteLength; + return wasEmpty; + } + + private _bufferTake(): VSBuffer { + const ret = VSBuffer.concat(this._data, this._totalLength); + this._data.length = 0; + this._totalLength = 0; + return ret; + } + + private _writeSoon(header: VSBuffer, data: VSBuffer): void { + if (this._bufferAdd(header, data)) { + platform.setImmediate(() => { + this._writeNow(); + }); + } + } + + private _writeNow(): void { + if (this._totalLength === 0) { + return; + } + this._socket.write(this._bufferTake()); + } +} + +/** + * A message has the following format: + * ``` + * /-------------------------------|------\ + * | HEADER | | + * |-------------------------------| DATA | + * | TYPE | ID | ACK | DATA_LENGTH | | + * \-------------------------------|------/ + * ``` + * The header is 9 bytes and consists of: + * - TYPE is 1 byte (ProtocolMessageType) - the message type + * - ID is 4 bytes (u32be) - the message id (can be 0 to indicate to be ignored) + * - ACK is 4 bytes (u32be) - the acknowledged message id (can be 0 to indicate to be ignored) + * - DATA_LENGTH is 4 bytes (u32be) - the length in bytes of DATA + * + * Only Regular messages are counted, other messages are not counted, nor acknowledged. + */ +export class Protocol extends Disposable implements IMessagePassingProtocol { + + private _socket: ISocket; + private _socketWriter: ProtocolWriter; + private _socketReader: ProtocolReader; + + private _onMessage = new Emitter(); + readonly onMessage: Event = this._onMessage.event; + + private _onClose = new Emitter(); + readonly onClose: Event = this._onClose.event; + + constructor(socket: ISocket) { + super(); + this._socket = socket; + this._socketWriter = this._register(new ProtocolWriter(this._socket)); + this._socketReader = this._register(new ProtocolReader(this._socket)); + + this._register(this._socketReader.onMessage((msg) => { + if (msg.type === ProtocolMessageType.Regular) { + this._onMessage.fire(msg.data); + } + })); + + this._register(this._socket.onClose(() => this._onClose.fire())); + } + + getSocket(): ISocket { + return this._socket; + } + + sendDisconnect(): void { + // Nothing to do... + } + + send(buffer: VSBuffer): void { + this._socketWriter.write(new ProtocolMessage(ProtocolMessageType.Regular, 0, 0, buffer)); + } +} + +export class Client extends IPCClient { + + static fromSocket(socket: ISocket, id: TContext): Client { + return new Client(new Protocol(socket), id); + } + + get onClose(): Event { return this.protocol.onClose; } + + constructor(private protocol: Protocol | PersistentProtocol, id: TContext) { + super(protocol, id); + } + + dispose(): void { + super.dispose(); + const socket = this.protocol.getSocket(); + this.protocol.sendDisconnect(); + this.protocol.dispose(); + socket.end(); + } +} + +/** + * Will ensure no messages are lost if there are no event listeners. + */ +export function createBufferedEvent(source: Event): Event { + let emitter: Emitter; + let hasListeners = false; + let isDeliveringMessages = false; + let bufferedMessages: T[] = []; + + const deliverMessages = () => { + if (isDeliveringMessages) { + return; + } + isDeliveringMessages = true; + while (hasListeners && bufferedMessages.length > 0) { + emitter.fire(bufferedMessages.shift()!); + } + isDeliveringMessages = false; + }; + + source((e: T) => { + bufferedMessages.push(e); + deliverMessages(); + }); + + emitter = new Emitter({ + onFirstListenerAdd: () => { + hasListeners = true; + // it is important to deliver these messages after this call, but before + // other messages have a chance to be received (to guarantee in order delivery) + // that's why we're using here nextTick and not other types of timeouts + if (typeof process !== 'undefined') { + process.nextTick(deliverMessages); + } else { + platform.setImmediate(deliverMessages); + } + }, + onLastListenerRemove: () => { + hasListeners = false; + } + }); + + return emitter.event; +} + +class QueueElement { + public readonly data: T; + public next: QueueElement | null; + + constructor(data: T) { + this.data = data; + this.next = null; + } +} + +class Queue { + + private _first: QueueElement | null; + private _last: QueueElement | null; + + constructor() { + this._first = null; + this._last = null; + } + + public peek(): T | null { + if (!this._first) { + return null; + } + return this._first.data; + } + + public toArray(): T[] { + let result: T[] = [], resultLen = 0; + let it = this._first; + while (it) { + result[resultLen++] = it.data; + it = it.next; + } + return result; + } + + public pop(): void { + if (!this._first) { + return; + } + if (this._first === this._last) { + this._first = null; + this._last = null; + return; + } + this._first = this._first.next; + } + + public push(item: T): void { + const element = new QueueElement(item); + if (!this._first) { + this._first = element; + this._last = element; + return; + } + this._last!.next = element; + this._last = element; + } +} + +/** + * Same as Protocol, but will actually track messages and acks. + * Moreover, it will ensure no messages are lost if there are no event listeners. + */ +export class PersistentProtocol implements IMessagePassingProtocol { + + private _isReconnecting: boolean; + + private _outgoingUnackMsg: Queue; + private _outgoingMsgId: number; + private _outgoingAckId: number; + private _outgoingAckTimeout: any | null; + + private _incomingMsgId: number; + private _incomingAckId: number; + private _incomingMsgLastTime: number; + private _incomingAckTimeout: any | null; + + private _outgoingKeepAliveTimeout: any | null; + private _incomingKeepAliveTimeout: any | null; + + private _socket: ISocket; + private _socketWriter: ProtocolWriter; + private _socketReader: ProtocolReader; + private _socketDisposables: IDisposable[]; + + private _onControlMessage = new Emitter(); + readonly onControlMessage: Event = createBufferedEvent(this._onControlMessage.event); + + private _onMessage = new Emitter(); + readonly onMessage: Event = createBufferedEvent(this._onMessage.event); + + private _onClose = new Emitter(); + readonly onClose: Event = createBufferedEvent(this._onClose.event); + + private _onSocketClose = new Emitter(); + readonly onSocketClose: Event = createBufferedEvent(this._onSocketClose.event); + + private _onSocketTimeout = new Emitter(); + readonly onSocketTimeout: Event = createBufferedEvent(this._onSocketTimeout.event); + + public get unacknowledgedCount(): number { + return this._outgoingMsgId - this._outgoingAckId; + } + + constructor(socket: ISocket, initialChunk: VSBuffer | null = null) { + this._isReconnecting = false; + this._outgoingUnackMsg = new Queue(); + this._outgoingMsgId = 0; + this._outgoingAckId = 0; + this._outgoingAckTimeout = null; + + this._incomingMsgId = 0; + this._incomingAckId = 0; + this._incomingMsgLastTime = 0; + this._incomingAckTimeout = null; + + this._outgoingKeepAliveTimeout = null; + this._incomingKeepAliveTimeout = null; + + this._socketDisposables = []; + this._socket = socket; + this._socketWriter = new ProtocolWriter(this._socket); + this._socketDisposables.push(this._socketWriter); + this._socketReader = new ProtocolReader(this._socket); + this._socketDisposables.push(this._socketReader); + this._socketDisposables.push(this._socketReader.onMessage(msg => this._receiveMessage(msg))); + this._socketDisposables.push(this._socket.onClose(() => this._onSocketClose.fire())); + if (initialChunk) { + this._socketReader.acceptChunk(initialChunk); + } + + this._sendKeepAliveCheck(); + this._recvKeepAliveCheck(); + } + + dispose(): void { + if (this._outgoingAckTimeout) { + clearTimeout(this._outgoingAckTimeout); + this._outgoingAckTimeout = null; + } + if (this._incomingAckTimeout) { + clearTimeout(this._incomingAckTimeout); + this._incomingAckTimeout = null; + } + if (this._outgoingKeepAliveTimeout) { + clearTimeout(this._outgoingKeepAliveTimeout); + this._outgoingKeepAliveTimeout = null; + } + if (this._incomingKeepAliveTimeout) { + clearTimeout(this._incomingKeepAliveTimeout); + this._incomingKeepAliveTimeout = null; + } + this._socketDisposables = dispose(this._socketDisposables); + } + + sendDisconnect(): void { + const msg = new ProtocolMessage(ProtocolMessageType.Disconnect, 0, 0, getEmptyBuffer()); + this._socketWriter.write(msg); + this._socketWriter.flush(); + } + + private _sendKeepAliveCheck(): void { + if (this._outgoingKeepAliveTimeout) { + // there will be a check in the near future + return; + } + + const timeSinceLastOutgoingMsg = Date.now() - this._socketWriter.lastWriteTime; + if (timeSinceLastOutgoingMsg >= ProtocolConstants.KeepAliveTime) { + // sufficient time has passed since last message was written, + // and no message from our side needed to be sent in the meantime, + // so we will send a message containing only a keep alive. + const msg = new ProtocolMessage(ProtocolMessageType.KeepAlive, 0, 0, getEmptyBuffer()); + this._socketWriter.write(msg); + this._sendKeepAliveCheck(); + return; + } + + this._outgoingKeepAliveTimeout = setTimeout(() => { + this._outgoingKeepAliveTimeout = null; + this._sendKeepAliveCheck(); + }, ProtocolConstants.KeepAliveTime - timeSinceLastOutgoingMsg + 5); + } + + private _recvKeepAliveCheck(): void { + if (this._incomingKeepAliveTimeout) { + // there will be a check in the near future + return; + } + + const timeSinceLastIncomingMsg = Date.now() - this._socketReader.lastReadTime; + if (timeSinceLastIncomingMsg >= ProtocolConstants.KeepAliveTimeoutTime) { + // Trash the socket + this._onSocketTimeout.fire(undefined); + return; + } + + this._incomingKeepAliveTimeout = setTimeout(() => { + this._incomingKeepAliveTimeout = null; + this._recvKeepAliveCheck(); + }, ProtocolConstants.KeepAliveTimeoutTime - timeSinceLastIncomingMsg + 5); + } + + public getSocket(): ISocket { + return this._socket; + } + + public beginAcceptReconnection(socket: ISocket, initialDataChunk: VSBuffer | null): void { + this._isReconnecting = true; + + this._socketDisposables = dispose(this._socketDisposables); + + this._socket = socket; + this._socketWriter = new ProtocolWriter(this._socket); + this._socketDisposables.push(this._socketWriter); + this._socketReader = new ProtocolReader(this._socket); + this._socketDisposables.push(this._socketReader); + this._socketDisposables.push(this._socketReader.onMessage(msg => this._receiveMessage(msg))); + this._socketDisposables.push(this._socket.onClose(() => this._onSocketClose.fire())); + this._socketReader.acceptChunk(initialDataChunk); + } + + public endAcceptReconnection(): void { + this._isReconnecting = false; + + // Send again all unacknowledged messages + const toSend = this._outgoingUnackMsg.toArray(); + for (let i = 0, len = toSend.length; i < len; i++) { + this._socketWriter.write(toSend[i]); + } + this._recvAckCheck(); + + this._sendKeepAliveCheck(); + this._recvKeepAliveCheck(); + } + + public acceptDisconnect(): void { + this._onClose.fire(); + } + + private _receiveMessage(msg: ProtocolMessage): void { + if (msg.ack > this._outgoingAckId) { + this._outgoingAckId = msg.ack; + do { + const first = this._outgoingUnackMsg.peek(); + if (first && first.id <= msg.ack) { + // this message has been confirmed, remove it + this._outgoingUnackMsg.pop(); + } else { + break; + } + } while (true); + } + + if (msg.type === ProtocolMessageType.Regular) { + if (msg.id > this._incomingMsgId) { + if (msg.id !== this._incomingMsgId + 1) { + console.error(`PROTOCOL CORRUPTION, LAST SAW MSG ${this._incomingMsgId} AND HAVE NOW RECEIVED MSG ${msg.id}`); + } + this._incomingMsgId = msg.id; + this._incomingMsgLastTime = Date.now(); + this._sendAckCheck(); + this._onMessage.fire(msg.data); + } + } else if (msg.type === ProtocolMessageType.Control) { + this._onControlMessage.fire(msg.data); + } else if (msg.type === ProtocolMessageType.Disconnect) { + this._onClose.fire(); + } + } + + readEntireBuffer(): VSBuffer { + return this._socketReader.readEntireBuffer(); + } + + flush(): void { + this._socketWriter.flush(); + } + + send(buffer: VSBuffer): void { + const myId = ++this._outgoingMsgId; + this._incomingAckId = this._incomingMsgId; + const msg = new ProtocolMessage(ProtocolMessageType.Regular, myId, this._incomingAckId, buffer); + this._outgoingUnackMsg.push(msg); + if (!this._isReconnecting) { + this._socketWriter.write(msg); + this._recvAckCheck(); + } + } + + /** + * Send a message which will not be part of the regular acknowledge flow. + * Use this for early control messages which are repeated in case of reconnection. + */ + sendControl(buffer: VSBuffer): void { + const msg = new ProtocolMessage(ProtocolMessageType.Control, 0, 0, buffer); + this._socketWriter.write(msg); + } + + private _sendAckCheck(): void { + if (this._incomingMsgId <= this._incomingAckId) { + // nothink to acknowledge + return; + } + + if (this._incomingAckTimeout) { + // there will be a check in the near future + return; + } + + const timeSinceLastIncomingMsg = Date.now() - this._incomingMsgLastTime; + if (timeSinceLastIncomingMsg >= ProtocolConstants.AcknowledgeTime) { + // sufficient time has passed since this message has been received, + // and no message from our side needed to be sent in the meantime, + // so we will send a message containing only an ack. + this._sendAck(); + return; + } + + this._incomingAckTimeout = setTimeout(() => { + this._incomingAckTimeout = null; + this._sendAckCheck(); + }, ProtocolConstants.AcknowledgeTime - timeSinceLastIncomingMsg + 5); + } + + private _recvAckCheck(): void { + if (this._outgoingMsgId <= this._outgoingAckId) { + // everything has been acknowledged + return; + } + + if (this._outgoingAckTimeout) { + // there will be a check in the near future + return; + } + + const oldestUnacknowledgedMsg = this._outgoingUnackMsg.peek()!; + const timeSinceOldestUnacknowledgedMsg = Date.now() - oldestUnacknowledgedMsg.writtenTime; + if (timeSinceOldestUnacknowledgedMsg >= ProtocolConstants.AcknowledgeTimeoutTime) { + // Trash the socket + this._onSocketTimeout.fire(undefined); + return; + } + + this._outgoingAckTimeout = setTimeout(() => { + this._outgoingAckTimeout = null; + this._recvAckCheck(); + }, ProtocolConstants.AcknowledgeTimeoutTime - timeSinceOldestUnacknowledgedMsg + 5); + } + + private _sendAck(): void { + if (this._incomingMsgId <= this._incomingAckId) { + // nothink to acknowledge + return; + } + + this._incomingAckId = this._incomingMsgId; + const msg = new ProtocolMessage(ProtocolMessageType.Ack, 0, this._incomingAckId, getEmptyBuffer()); + this._socketWriter.write(msg); + } +} diff --git a/src/vs/base/parts/ipc/node/ipc.ts b/src/vs/base/parts/ipc/common/ipc.ts similarity index 82% rename from src/vs/base/parts/ipc/node/ipc.ts rename to src/vs/base/parts/ipc/common/ipc.ts index e6c84e6b949..e0205092202 100644 --- a/src/vs/base/parts/ipc/node/ipc.ts +++ b/src/vs/base/parts/ipc/common/ipc.ts @@ -3,11 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; import { Event, Emitter, Relay } from 'vs/base/common/event'; -import { always, CancelablePromise, createCancelablePromise, timeout } from 'vs/base/common/async'; +import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; +import { CancelablePromise, createCancelablePromise, timeout } from 'vs/base/common/async'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import * as errors from 'vs/base/common/errors'; +import { IServerChannel, IChannel } from 'vs/base/parts/ipc/common/ipc'; +import { VSBuffer } from 'vs/base/common/buffer'; + +/** + * An `IChannel` is an abstraction over a collection of commands. + * You can `call` several commands on a channel, each taking at + * most one single argument. A `call` always returns a promise + * with at most one single return value. + */ +export interface IChannel { + call(command: string, arg?: any, cancellationToken?: CancellationToken): Promise; + listen(event: string, arg?: any): Event; +} + +/** + * An `IServerChannel` is the counter part to `IChannel`, + * on the server-side. You should implement this interface + * if you'd like to handle remote promises or events. + */ +export interface IServerChannel { + call(ctx: TContext, command: string, arg?: any, cancellationToken?: CancellationToken): Promise; + listen(ctx: TContext, event: string, arg?: any): Event; +} + export const enum RequestType { Promise = 100, @@ -42,8 +66,8 @@ interface IHandler { } export interface IMessagePassingProtocol { - send(buffer: Buffer): void; - onMessage: Event; + send(buffer: VSBuffer): void; + onMessage: Event; } enum State { @@ -51,27 +75,6 @@ enum State { Idle } -/** - * An `IChannel` is an abstraction over a collection of commands. - * You can `call` several commands on a channel, each taking at - * most one single argument. A `call` always returns a promise - * with at most one single return value. - */ -export interface IChannel { - call(command: string, arg?: any, cancellationToken?: CancellationToken): Promise; - listen(event: string, arg?: any): Event; -} - -/** - * An `IServerChannel` is the couter part to `IChannel`, - * on the server-side. You should implement this interface - * if you'd like to handle remote promises or events. - */ -export interface IServerChannel { - call(ctx: TContext, command: string, arg?: any, cancellationToken?: CancellationToken): Promise; - listen(ctx: TContext, event: string, arg?: any): Event; -} - /** * An `IChannelServer` hosts a collection of channels. You are * able to register channels onto it, provided a channel name. @@ -119,35 +122,35 @@ export interface IRoutingChannelClient { } interface IReader { - read(bytes: number): Buffer; + read(bytes: number): VSBuffer; } interface IWriter { - write(buffer: Buffer): void; + write(buffer: VSBuffer): void; } class BufferReader implements IReader { private pos = 0; - constructor(private buffer: Buffer) { } + constructor(private buffer: VSBuffer) { } - read(bytes: number): Buffer { + read(bytes: number): VSBuffer { const result = this.buffer.slice(this.pos, this.pos + bytes); - this.pos += result.length; + this.pos += result.byteLength; return result; } } class BufferWriter implements IWriter { - private buffers: Buffer[] = []; + private buffers: VSBuffer[] = []; - get buffer(): Buffer { - return Buffer.concat(this.buffers); + get buffer(): VSBuffer { + return VSBuffer.concat(this.buffers); } - write(buffer: Buffer): void { + write(buffer: VSBuffer): void { this.buffers.push(buffer); } } @@ -156,12 +159,13 @@ enum DataType { Undefined = 0, String = 1, Buffer = 2, - Array = 3, - Object = 4 + VSBuffer = 3, + Array = 4, + Object = 5 } -function createSizeBuffer(size: number): Buffer { - const result = Buffer.allocUnsafe(4); +function createSizeBuffer(size: number): VSBuffer { + const result = VSBuffer.alloc(4); result.writeUInt32BE(size, 0); return result; } @@ -170,25 +174,40 @@ function readSizeBuffer(reader: IReader): number { return reader.read(4).readUInt32BE(0); } +function createOneByteBuffer(value: number): VSBuffer { + const result = VSBuffer.alloc(1); + result.writeUInt8(value, 0); + return result; +} + const BufferPresets = { - Undefined: Buffer.alloc(1, DataType.Undefined), - String: Buffer.alloc(1, DataType.String), - Buffer: Buffer.alloc(1, DataType.Buffer), - Array: Buffer.alloc(1, DataType.Array), - Object: Buffer.alloc(1, DataType.Object) + Undefined: createOneByteBuffer(DataType.Undefined), + String: createOneByteBuffer(DataType.String), + Buffer: createOneByteBuffer(DataType.Buffer), + VSBuffer: createOneByteBuffer(DataType.VSBuffer), + Array: createOneByteBuffer(DataType.Array), + Object: createOneByteBuffer(DataType.Object), }; +declare var Buffer: any; +const hasBuffer = (typeof Buffer !== 'undefined'); + function serialize(writer: IWriter, data: any): void { if (typeof data === 'undefined') { writer.write(BufferPresets.Undefined); } else if (typeof data === 'string') { - const buffer = Buffer.from(data); + const buffer = VSBuffer.fromString(data); writer.write(BufferPresets.String); - writer.write(createSizeBuffer(buffer.length)); + writer.write(createSizeBuffer(buffer.byteLength)); writer.write(buffer); - } else if (Buffer.isBuffer(data)) { + } else if (hasBuffer && Buffer.isBuffer(data)) { + const buffer = VSBuffer.wrap(data); writer.write(BufferPresets.Buffer); - writer.write(createSizeBuffer(data.length)); + writer.write(createSizeBuffer(buffer.byteLength)); + writer.write(buffer); + } else if (data instanceof VSBuffer) { + writer.write(BufferPresets.VSBuffer); + writer.write(createSizeBuffer(data.byteLength)); writer.write(data); } else if (Array.isArray(data)) { writer.write(BufferPresets.Array); @@ -198,9 +217,9 @@ function serialize(writer: IWriter, data: any): void { serialize(writer, el); } } else { - const buffer = Buffer.from(JSON.stringify(data)); + const buffer = VSBuffer.fromString(JSON.stringify(data)); writer.write(BufferPresets.Object); - writer.write(createSizeBuffer(buffer.length)); + writer.write(createSizeBuffer(buffer.byteLength)); writer.write(buffer); } } @@ -211,7 +230,8 @@ function deserialize(reader: IReader): any { switch (type) { case DataType.Undefined: return undefined; case DataType.String: return reader.read(readSizeBuffer(reader)).toString(); - case DataType.Buffer: return reader.read(readSizeBuffer(reader)); + case DataType.Buffer: return reader.read(readSizeBuffer(reader)).buffer; + case DataType.VSBuffer: return reader.read(readSizeBuffer(reader)); case DataType.Array: { const length = readSizeBuffer(reader); const result: any[] = []; @@ -226,19 +246,31 @@ function deserialize(reader: IReader): any { } } +interface PendingRequest { + request: IRawPromiseRequest | IRawEventListenRequest; + timeoutTimer: any; +} + export class ChannelServer implements IChannelServer, IDisposable { private channels = new Map>(); private activeRequests = new Map(); private protocolListener: IDisposable | null; - constructor(private protocol: IMessagePassingProtocol, private ctx: TContext) { + // Requests might come in for channels which are not yet registered. + // They will timeout after `timeoutDelay`. + private pendingRequests = new Map(); + + constructor(private protocol: IMessagePassingProtocol, private ctx: TContext, private timeoutDelay: number = 1000) { this.protocolListener = this.protocol.onMessage(msg => this.onRawMessage(msg)); this.sendResponse({ type: ResponseType.Initialize }); } registerChannel(channelName: string, channel: IServerChannel): void { this.channels.set(channelName, channel); + + // https://github.com/microsoft/vscode/issues/72531 + setTimeout(() => this.flushPendingRequests(channelName), 0); } private sendResponse(response: IRawResponse): void { @@ -261,7 +293,7 @@ export class ChannelServer implements IChannelServer implements IChannelServer implements IChannelServer; @@ -326,6 +364,11 @@ export class ChannelServer implements IChannelServer this.sendResponse({ id, data, type: ResponseType.EventFire })); @@ -342,6 +385,46 @@ export class ChannelServer implements IChannelServer { + console.error(`Unknown channel: ${request.channelName}`); + + if (request.type === RequestType.Promise) { + this.sendResponse({ + id: request.id, + data: { name: 'Unknown channel', message: `Channel name '${request.channelName}' timed out after ${this.timeoutDelay}ms`, stack: undefined }, + type: ResponseType.PromiseError + }); + } + }, this.timeoutDelay); + + pendingRequests.push({ request, timeoutTimer: timer }); + } + + private flushPendingRequests(channelName: string): void { + const requests = this.pendingRequests.get(channelName); + + if (requests) { + for (const request of requests) { + clearTimeout(request.timeoutTimer); + + switch (request.request.type) { + case RequestType.Promise: this.onPromise(request.request); break; + case RequestType.EventListen: this.onEventListen(request.request); break; + } + } + + this.pendingRequests.delete(channelName); + } + } + public dispose(): void { if (this.protocolListener) { this.protocolListener.dispose(); @@ -438,13 +521,11 @@ export class ChannelClient implements IChannelClient, IDisposable { }; const cancellationTokenListener = cancellationToken.onCancellationRequested(cancel); - disposable = combinedDisposable([toDisposable(cancel), cancellationTokenListener]); + disposable = combinedDisposable(toDisposable(cancel), cancellationTokenListener); this.activeRequests.add(disposable); }); - always(result, () => this.activeRequests.delete(disposable)); - - return result; + return result.finally(() => this.activeRequests.delete(disposable)); } private requestEvent(channelName: string, name: string, arg?: any): Event { @@ -499,7 +580,7 @@ export class ChannelClient implements IChannelClient, IDisposable { this.sendBuffer(writer.buffer); } - private sendBuffer(message: Buffer): void { + private sendBuffer(message: VSBuffer): void { try { this.protocol.send(message); } catch (err) { @@ -507,7 +588,7 @@ export class ChannelClient implements IChannelClient, IDisposable { } } - private onBuffer(message: Buffer): void { + private onBuffer(message: VSBuffer): void { const reader = new BufferReader(message); const header = deserialize(reader); const body = deserialize(reader); @@ -563,6 +644,7 @@ export interface ClientConnectionEvent { } interface Connection extends Client { + readonly channelServer: ChannelServer; readonly channelClient: ChannelClient; } @@ -601,7 +683,7 @@ export class IPCServer implements IChannelServer, I this.channels.forEach((channel, name) => channelServer.registerChannel(name, channel)); - const connection: Connection = { channelClient, ctx }; + const connection: Connection = { channelServer, channelClient, ctx }; this._connections.add(connection); this._onDidChangeConnections.fire(connection); @@ -637,6 +719,10 @@ export class IPCServer implements IChannelServer, I registerChannel(channelName: string, channel: IServerChannel): void { this.channels.set(channelName, channel); + + this._connections.forEach(connection => { + connection.channelServer.registerChannel(channelName, channel); + }); } dispose(): void { @@ -684,7 +770,7 @@ export class IPCClient implements IChannelClient, IChannelSer export function getDelayedChannel(promise: Promise): T { return { call(command: string, arg?: any, cancellationToken?: CancellationToken): Promise { - return promise.then(c => c.call(command, arg, cancellationToken)); + return promise.then(c => c.call(command, arg, cancellationToken)); }, listen(event: string, arg?: any): Event { @@ -746,4 +832,4 @@ export class StaticRouter implements IClientRouter await Event.toPromise(hub.onDidChangeConnections); return await this.route(hub); } -} \ No newline at end of file +} diff --git a/src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts b/src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts index 225370373a7..2690300b83a 100644 --- a/src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts +++ b/src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts @@ -4,17 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import { Event } from 'vs/base/common/event'; -import { IPCClient } from 'vs/base/parts/ipc/node/ipc'; +import { IPCClient } from 'vs/base/parts/ipc/common/ipc'; import { Protocol } from 'vs/base/parts/ipc/node/ipc.electron'; import { ipcRenderer } from 'electron'; import { IDisposable } from 'vs/base/common/lifecycle'; +import { VSBuffer } from 'vs/base/common/buffer'; export class Client extends IPCClient implements IDisposable { private protocol: Protocol; private static createProtocol(): Protocol { - const onMessage = Event.fromNodeEventEmitter(ipcRenderer, 'ipc:message', (_, message: string) => message); + const onMessage = Event.fromNodeEventEmitter(ipcRenderer, 'ipc:message', (_, message: Buffer) => VSBuffer.wrap(message)); ipcRenderer.send('ipc:hello'); return new Protocol(ipcRenderer, onMessage); } diff --git a/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts b/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts index e90f23301a4..c5fbbb4e65b 100644 --- a/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts +++ b/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts @@ -3,30 +3,44 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Event } from 'vs/base/common/event'; -import { IPCServer, ClientConnectionEvent } from 'vs/base/parts/ipc/node/ipc'; +import { Event, Emitter } from 'vs/base/common/event'; +import { IPCServer, ClientConnectionEvent } from 'vs/base/parts/ipc/common/ipc'; import { Protocol } from 'vs/base/parts/ipc/node/ipc.electron'; import { ipcMain } from 'electron'; +import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { VSBuffer } from 'vs/base/common/buffer'; interface IIPCEvent { event: { sender: Electron.WebContents; }; - message: string; + message: Buffer | null; } -function createScopedOnMessageEvent(senderId: number, eventName: string): Event { - const onMessage = Event.fromNodeEventEmitter(ipcMain, eventName, (event, message: string) => ({ event, message })); +function createScopedOnMessageEvent(senderId: number, eventName: string): Event { + const onMessage = Event.fromNodeEventEmitter(ipcMain, eventName, (event, message) => ({ event, message })); const onMessageFromSender = Event.filter(onMessage, ({ event }) => event.sender.id === senderId); - return Event.map(onMessageFromSender, ({ message }) => message); + return Event.map(onMessageFromSender, ({ message }) => message ? VSBuffer.wrap(message) : message); } export class Server extends IPCServer { + private static Clients = new Map(); + private static getOnDidClientConnect(): Event { const onHello = Event.fromNodeEventEmitter(ipcMain, 'ipc:hello', ({ sender }) => sender); return Event.map(onHello, webContents => { - const onMessage = createScopedOnMessageEvent(webContents.id, 'ipc:message'); - const onDidClientDisconnect = Event.signal(createScopedOnMessageEvent(webContents.id, 'ipc:disconnect')); + const id = webContents.id; + const client = Server.Clients.get(id); + + if (client) { + client.dispose(); + } + + const onDidClientReconnect = new Emitter(); + Server.Clients.set(id, toDisposable(() => onDidClientReconnect.fire())); + + const onMessage = createScopedOnMessageEvent(id, 'ipc:message') as Event; + const onDidClientDisconnect = Event.any(Event.signal(createScopedOnMessageEvent(id, 'ipc:disconnect')), onDidClientReconnect.event); const protocol = new Protocol(webContents, onMessage); return { protocol, onDidClientDisconnect }; diff --git a/src/vs/base/parts/ipc/node/ipc.cp.ts b/src/vs/base/parts/ipc/node/ipc.cp.ts index 2217c707d22..9104deb503c 100644 --- a/src/vs/base/parts/ipc/node/ipc.cp.ts +++ b/src/vs/base/parts/ipc/node/ipc.cp.ts @@ -5,14 +5,15 @@ import { ChildProcess, fork, ForkOptions } from 'child_process'; import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle'; -import { Delayer, always, createCancelablePromise } from 'vs/base/common/async'; +import { Delayer, createCancelablePromise } from 'vs/base/common/async'; import { deepClone, assign } from 'vs/base/common/objects'; import { Emitter, Event } from 'vs/base/common/event'; import { createQueuedSender } from 'vs/base/node/processes'; -import { ChannelServer as IPCServer, ChannelClient as IPCClient, IChannelClient, IChannel } from 'vs/base/parts/ipc/node/ipc'; -import { isRemoteConsoleLog, log } from 'vs/base/node/console'; +import { IChannel, ChannelServer as IPCServer, ChannelClient as IPCClient, IChannelClient } from 'vs/base/parts/ipc/common/ipc'; +import { isRemoteConsoleLog, log } from 'vs/base/common/console'; import { CancellationToken } from 'vs/base/common/cancellation'; import * as errors from 'vs/base/common/errors'; +import { VSBuffer } from 'vs/base/common/buffer'; /** * This implementation doesn't perform well since it uses base64 encoding for buffers. @@ -25,11 +26,11 @@ export class Server extends IPCServer { send: r => { try { if (process.send) { - process.send(r.toString('base64')); + process.send((r.buffer).toString('base64')); } } catch (e) { /* not much to do */ } }, - onMessage: Event.fromNodeEventEmitter(process, 'message', msg => Buffer.from(msg, 'base64')) + onMessage: Event.fromNodeEventEmitter(process, 'message', msg => VSBuffer.wrap(Buffer.from(msg, 'base64'))) }, ctx); process.once('disconnect', () => this.dispose()); @@ -132,7 +133,7 @@ export class Client implements IChannelClient, IDisposable { const disposable = toDisposable(() => result.cancel()); this.activeRequests.add(disposable); - always(result, () => { + result.finally(() => { cancellationTokenListener.dispose(); this.activeRequests.delete(disposable); @@ -198,7 +199,7 @@ export class Client implements IChannelClient, IDisposable { this.child = fork(this.modulePath, args, forkOpts); - const onMessageEmitter = new Emitter(); + const onMessageEmitter = new Emitter(); const onRawMessage = Event.fromNodeEventEmitter(this.child, 'message', msg => msg); onRawMessage(msg => { @@ -210,11 +211,11 @@ export class Client implements IChannelClient, IDisposable { } // Anything else goes to the outside - onMessageEmitter.fire(Buffer.from(msg, 'base64')); + onMessageEmitter.fire(VSBuffer.wrap(Buffer.from(msg, 'base64'))); }); const sender = this.options.useQueue ? createQueuedSender(this.child) : this.child; - const send = (r: Buffer) => this.child && this.child.connected && sender.send(r.toString('base64')); + const send = (r: VSBuffer) => this.child && this.child.connected && sender.send((r.buffer).toString('base64')); const onMessage = onMessageEmitter.event; const protocol = { send, onMessage }; diff --git a/src/vs/base/parts/ipc/node/ipc.electron.ts b/src/vs/base/parts/ipc/node/ipc.electron.ts index 831a27377c1..09c97ba47b1 100644 --- a/src/vs/base/parts/ipc/node/ipc.electron.ts +++ b/src/vs/base/parts/ipc/node/ipc.electron.ts @@ -3,33 +3,21 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc'; -import { Event, Emitter } from 'vs/base/common/event'; - -/** - * This implementation doesn't perform well since it uses base64 encoding for buffers. - * Electron 3.0 should have suport for buffers in IPC: https://github.com/electron/electron/pull/13055 - */ +import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; +import { Event } from 'vs/base/common/event'; +import { VSBuffer } from 'vs/base/common/buffer'; export interface Sender { - send(channel: string, msg: string | null): void; + send(channel: string, msg: Buffer | null): void; } export class Protocol implements IMessagePassingProtocol { - private listener: IDisposable; + constructor(private sender: Sender, readonly onMessage: Event) { } - private _onMessage = new Emitter(); - get onMessage(): Event { return this._onMessage.event; } - - constructor(private sender: Sender, onMessageEvent: Event) { - onMessageEvent(msg => this._onMessage.fire(Buffer.from(msg, 'base64'))); - } - - send(message: Buffer): void { + send(message: VSBuffer): void { try { - this.sender.send('ipc:message', message.toString('base64')); + this.sender.send('ipc:message', (message.buffer)); } catch (e) { // systems are going down } @@ -37,6 +25,5 @@ export class Protocol implements IMessagePassingProtocol { dispose(): void { this.sender.send('ipc:disconnect', null); - this.listener = dispose(this.listener); } } \ No newline at end of file diff --git a/src/vs/base/parts/ipc/node/ipc.net.ts b/src/vs/base/parts/ipc/node/ipc.net.ts index 40ddff4c22d..11e4f516f22 100644 --- a/src/vs/base/parts/ipc/node/ipc.net.ts +++ b/src/vs/base/parts/ipc/node/ipc.net.ts @@ -5,12 +5,256 @@ import { Socket, Server as NetServer, createConnection, createServer } from 'net'; import { Event, Emitter } from 'vs/base/common/event'; -import { IMessagePassingProtocol, ClientConnectionEvent, IPCServer, IPCClient } from 'vs/base/parts/ipc/node/ipc'; -import { join } from 'path'; +import { ClientConnectionEvent, IPCServer } from 'vs/base/parts/ipc/common/ipc'; +import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; import { generateUuid } from 'vs/base/common/uuid'; -import { IDisposable } from 'vs/base/common/lifecycle'; -import { TimeoutTimer } from 'vs/base/common/async'; +import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { VSBuffer } from 'vs/base/common/buffer'; +import { ISocket, Protocol, Client, ChunkStream } from 'vs/base/parts/ipc/common/ipc.net'; + +export class NodeSocket implements ISocket { + public readonly socket: Socket; + + constructor(socket: Socket) { + this.socket = socket; + } + + public dispose(): void { + this.socket.destroy(); + } + + public onData(_listener: (e: VSBuffer) => void): IDisposable { + const listener = (buff: Buffer) => _listener(VSBuffer.wrap(buff)); + this.socket.on('data', listener); + return { + dispose: () => this.socket.off('data', listener) + }; + } + + public onClose(listener: () => void): IDisposable { + this.socket.on('close', listener); + return { + dispose: () => this.socket.off('close', listener) + }; + } + + public onEnd(listener: () => void): IDisposable { + this.socket.on('end', listener); + return { + dispose: () => this.socket.off('end', listener) + }; + } + + public write(buffer: VSBuffer): void { + // return early if socket has been destroyed in the meantime + if (this.socket.destroyed) { + return; + } + + // we ignore the returned value from `write` because we would have to cached the data + // anyways and nodejs is already doing that for us: + // > https://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback + // > However, the false return value is only advisory and the writable stream will unconditionally + // > accept and buffer chunk even if it has not not been allowed to drain. + this.socket.write(buffer.buffer); + } + + public end(): void { + this.socket.end(); + } +} + +const enum Constants { + MinHeaderByteSize = 2 +} + +const enum ReadState { + PeekHeader = 1, + ReadHeader = 2, + ReadBody = 3, + Fin = 4 +} + +/** + * See https://tools.ietf.org/html/rfc6455#section-5.2 + */ +export class WebSocketNodeSocket extends Disposable implements ISocket { + + public readonly socket: NodeSocket; + private readonly _incomingData: ChunkStream; + private readonly _onData = this._register(new Emitter()); + + private readonly _state = { + state: ReadState.PeekHeader, + readLen: Constants.MinHeaderByteSize, + mask: 0 + }; + + constructor(socket: NodeSocket) { + super(); + this.socket = socket; + this._incomingData = new ChunkStream(); + this._register(this.socket.onData(data => this._acceptChunk(data))); + } + + public dispose(): void { + this.socket.dispose(); + } + + public onData(listener: (e: VSBuffer) => void): IDisposable { + return this._onData.event(listener); + } + + public onClose(listener: () => void): IDisposable { + return this.socket.onClose(listener); + } + + public onEnd(listener: () => void): IDisposable { + return this.socket.onEnd(listener); + } + + public write(buffer: VSBuffer): void { + let headerLen = Constants.MinHeaderByteSize; + if (buffer.byteLength < 126) { + headerLen += 0; + } else if (buffer.byteLength < 2 ** 16) { + headerLen += 2; + } else { + headerLen += 8; + } + const header = VSBuffer.alloc(headerLen); + + header.writeUInt8(0b10000010, 0); + if (buffer.byteLength < 126) { + header.writeUInt8(buffer.byteLength, 1); + } else if (buffer.byteLength < 2 ** 16) { + header.writeUInt8(126, 1); + let offset = 1; + header.writeUInt8((buffer.byteLength >>> 8) & 0b11111111, ++offset); + header.writeUInt8((buffer.byteLength >>> 0) & 0b11111111, ++offset); + } else { + header.writeUInt8(127, 1); + let offset = 1; + header.writeUInt8(0, ++offset); + header.writeUInt8(0, ++offset); + header.writeUInt8(0, ++offset); + header.writeUInt8(0, ++offset); + header.writeUInt8((buffer.byteLength >>> 24) & 0b11111111, ++offset); + header.writeUInt8((buffer.byteLength >>> 16) & 0b11111111, ++offset); + header.writeUInt8((buffer.byteLength >>> 8) & 0b11111111, ++offset); + header.writeUInt8((buffer.byteLength >>> 0) & 0b11111111, ++offset); + } + + this.socket.write(VSBuffer.concat([header, buffer])); + } + + public end(): void { + this.socket.end(); + } + + private _acceptChunk(data: VSBuffer): void { + if (data.byteLength === 0) { + return; + } + + this._incomingData.acceptChunk(data); + + while (this._incomingData.byteLength >= this._state.readLen) { + + if (this._state.state === ReadState.PeekHeader) { + // peek to see if we can read the entire header + const peekHeader = this._incomingData.peek(this._state.readLen); + // const firstByte = peekHeader.readUInt8(0); + // const finBit = (firstByte & 0b10000000) >>> 7; + const secondByte = peekHeader.readUInt8(1); + const hasMask = (secondByte & 0b10000000) >>> 7; + const len = (secondByte & 0b01111111); + + this._state.state = ReadState.ReadHeader; + this._state.readLen = Constants.MinHeaderByteSize + (hasMask ? 4 : 0) + (len === 126 ? 2 : 0) + (len === 127 ? 8 : 0); + this._state.mask = 0; + + } else if (this._state.state === ReadState.ReadHeader) { + // read entire header + const header = this._incomingData.read(this._state.readLen); + const secondByte = header.readUInt8(1); + const hasMask = (secondByte & 0b10000000) >>> 7; + let len = (secondByte & 0b01111111); + + let offset = 1; + if (len === 126) { + len = ( + header.readUInt8(++offset) * 2 ** 8 + + header.readUInt8(++offset) + ); + } else if (len === 127) { + len = ( + header.readUInt8(++offset) * 0 + + header.readUInt8(++offset) * 0 + + header.readUInt8(++offset) * 0 + + header.readUInt8(++offset) * 0 + + header.readUInt8(++offset) * 2 ** 24 + + header.readUInt8(++offset) * 2 ** 16 + + header.readUInt8(++offset) * 2 ** 8 + + header.readUInt8(++offset) + ); + } + + let mask = 0; + if (hasMask) { + mask = ( + header.readUInt8(++offset) * 2 ** 24 + + header.readUInt8(++offset) * 2 ** 16 + + header.readUInt8(++offset) * 2 ** 8 + + header.readUInt8(++offset) + ); + } + + this._state.state = ReadState.ReadBody; + this._state.readLen = len; + this._state.mask = mask; + + } else if (this._state.state === ReadState.ReadBody) { + // read body + + const body = this._incomingData.read(this._state.readLen); + unmask(body, this._state.mask); + + this._state.state = ReadState.PeekHeader; + this._state.readLen = Constants.MinHeaderByteSize; + this._state.mask = 0; + + this._onData.fire(body); + } + } + } +} + +function unmask(buffer: VSBuffer, mask: number): void { + if (mask === 0) { + return; + } + let cnt = buffer.byteLength >>> 2; + for (let i = 0; i < cnt; i++) { + const v = buffer.readUInt32BE(i * 4); + buffer.writeUInt32BE(v ^ mask, i * 4); + } + let offset = cnt * 4; + let bytesLeft = buffer.byteLength - offset; + const m3 = (mask >>> 24) & 0b11111111; + const m2 = (mask >>> 16) & 0b11111111; + const m1 = (mask >>> 8) & 0b11111111; + if (bytesLeft >= 1) { + buffer.writeUInt8(buffer.readUInt8(offset) ^ m3, offset); + } + if (bytesLeft >= 2) { + buffer.writeUInt8(buffer.readUInt8(offset + 1) ^ m2, offset + 1); + } + if (bytesLeft >= 3) { + buffer.writeUInt8(buffer.readUInt8(offset + 2) ^ m1, offset + 2); + } +} export function generateRandomPipeName(): string { const randomSuffix = generateUuid(); @@ -22,195 +266,13 @@ export function generateRandomPipeName(): string { } } -/** - * A message has the following format: - * - * [bodyLen|message] - * [header^|data^^^] - * [u32be^^|buffer^] - */ - -export class Protocol implements IDisposable, IMessagePassingProtocol { - - private static readonly _headerLen = 4; - - private _isDisposed: boolean; - private _chunks: Buffer[]; - - private _firstChunkTimer: TimeoutTimer; - private _socketDataListener: (data: Buffer) => void; - private _socketEndListener: () => void; - private _socketCloseListener: () => void; - - private _onMessage = new Emitter(); - readonly onMessage: Event = this._onMessage.event; - - private _onClose = new Emitter(); - readonly onClose: Event = this._onClose.event; - - constructor(private _socket: Socket, firstDataChunk?: Buffer) { - this._isDisposed = false; - this._chunks = []; - - let totalLength = 0; - - const state = { - readHead: true, - bodyLen: -1, - }; - - const acceptChunk = (data: Buffer) => { - - this._chunks.push(data); - totalLength += data.length; - - while (totalLength > 0) { - - if (state.readHead) { - // expecting header -> read 5bytes for header - // information: `bodyIsJson` and `bodyLen` - if (totalLength >= Protocol._headerLen) { - const all = Buffer.concat(this._chunks); - - state.bodyLen = all.readUInt32BE(0); - state.readHead = false; - - const rest = all.slice(Protocol._headerLen); - totalLength = rest.length; - this._chunks = [rest]; - - } else { - break; - } - } - - if (!state.readHead) { - // expecting body -> read bodyLen-bytes for - // the actual message or wait for more data - if (totalLength >= state.bodyLen) { - - const all = Buffer.concat(this._chunks); - const buffer = all.slice(0, state.bodyLen); - - // ensure the getBuffer returns a valid value if invoked from the event listeners - const rest = all.slice(state.bodyLen); - totalLength = rest.length; - this._chunks = [rest]; - - state.bodyLen = -1; - state.readHead = true; - - this._onMessage.fire(buffer); - - if (this._isDisposed) { - // check if an event listener lead to our disposal - break; - } - } else { - break; - } - } - } - }; - - const acceptFirstDataChunk = () => { - if (firstDataChunk && firstDataChunk.length > 0) { - let tmp = firstDataChunk; - firstDataChunk = undefined; - acceptChunk(tmp); - } - }; - - // Make sure to always handle the firstDataChunk if no more `data` event comes in - this._firstChunkTimer = new TimeoutTimer(); - this._firstChunkTimer.setIfNotSet(() => { - acceptFirstDataChunk(); - }, 0); - - this._socketDataListener = (data: Buffer) => { - acceptFirstDataChunk(); - acceptChunk(data); - }; - _socket.on('data', this._socketDataListener); - - this._socketEndListener = () => { - acceptFirstDataChunk(); - }; - _socket.on('end', this._socketEndListener); - - this._socketCloseListener = () => { - this._onClose.fire(); - }; - _socket.once('close', this._socketCloseListener); - } - - dispose(): void { - this._isDisposed = true; - this._firstChunkTimer.dispose(); - this._socket.removeListener('data', this._socketDataListener); - this._socket.removeListener('end', this._socketEndListener); - this._socket.removeListener('close', this._socketCloseListener); - } - - end(): void { - this._socket.end(); - } - - getBuffer(): Buffer { - return Buffer.concat(this._chunks); - } - - send(buffer: Buffer): void { - const header = Buffer.allocUnsafe(Protocol._headerLen); - header.writeUInt32BE(buffer.length, 0, true); - this._writeSoon(header, buffer); - } - - private _writeBuffer = new class { - - private _data: Buffer[] = []; - private _totalLength = 0; - - add(head: Buffer, body: Buffer): boolean { - const wasEmpty = this._totalLength === 0; - this._data.push(head, body); - this._totalLength += head.length + body.length; - return wasEmpty; - } - - take(): Buffer { - const ret = Buffer.concat(this._data, this._totalLength); - this._data.length = 0; - this._totalLength = 0; - return ret; - } - }; - - private _writeSoon(header: Buffer, data: Buffer): void { - if (this._writeBuffer.add(header, data)) { - setImmediate(() => { - // return early if socket has been destroyed in the meantime - if (this._socket.destroyed) { - return; - } - // we ignore the returned value from `write` because we would have to cached the data - // anyways and nodejs is already doing that for us: - // > https://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback - // > However, the false return value is only advisory and the writable stream will unconditionally - // > accept and buffer chunk even if it has not not been allowed to drain. - this._socket.write(this._writeBuffer.take()); - }); - } - } -} - export class Server extends IPCServer { private static toClientConnectionEvent(server: NetServer): Event { const onConnection = Event.fromNodeEventEmitter(server, 'connection'); return Event.map(onConnection, socket => ({ - protocol: new Protocol(socket), + protocol: new Protocol(new NodeSocket(socket)), onDidClientDisconnect: Event.once(Event.fromNodeEventEmitter(socket, 'close')) })); } @@ -231,24 +293,6 @@ export class Server extends IPCServer { } } -export class Client extends IPCClient { - - static fromSocket(socket: Socket, id: TContext): Client { - return new Client(new Protocol(socket), id); - } - - get onClose(): Event { return this.protocol.onClose; } - - constructor(private protocol: Protocol | BufferedProtocol, id: TContext) { - super(protocol, id); - } - - dispose(): void { - super.dispose(); - this.protocol.end(); - } -} - export function serve(port: number): Promise; export function serve(namedPipe: string): Promise; export function serve(hook: any): Promise { @@ -270,74 +314,9 @@ export function connect(hook: any, clientId: string): Promise { return new Promise((c, e) => { const socket = createConnection(hook, () => { socket.removeListener('error', e); - c(Client.fromSocket(socket, clientId)); + c(Client.fromSocket(new NodeSocket(socket), clientId)); }); socket.once('error', e); }); } - -/** - * Will ensure no messages are lost if there are no event listeners. - */ -function createBufferedEvent(source: Event): Event { - let emitter: Emitter; - let hasListeners = false; - let isDeliveringMessages = false; - let bufferedMessages: T[] = []; - - const deliverMessages = () => { - if (isDeliveringMessages) { - return; - } - isDeliveringMessages = true; - while (hasListeners && bufferedMessages.length > 0) { - emitter.fire(bufferedMessages.shift()!); - } - isDeliveringMessages = false; - }; - - source((e: T) => { - bufferedMessages.push(e); - deliverMessages(); - }); - - emitter = new Emitter({ - onFirstListenerAdd: () => { - hasListeners = true; - // it is important to deliver these messages after this call, but before - // other messages have a chance to be received (to guarantee in order delivery) - // that's why we're using here nextTick and not other types of timeouts - process.nextTick(deliverMessages); - }, - onLastListenerRemove: () => { - hasListeners = false; - } - }); - - return emitter.event; -} - -/** - * Will ensure no messages are lost if there are no event listeners. - */ -export class BufferedProtocol implements IMessagePassingProtocol { - - private readonly _actual: Protocol; - public readonly onMessage: Event; - public readonly onClose: Event; - - constructor(actual: Protocol) { - this._actual = actual; - this.onMessage = createBufferedEvent(this._actual.onMessage); - this.onClose = createBufferedEvent(this._actual.onClose); - } - - public send(buffer: Buffer): void { - this._actual.send(buffer); - } - - public end(): void { - this._actual.end(); - } -} diff --git a/src/vs/base/parts/ipc/test/node/ipc.cp.test.ts b/src/vs/base/parts/ipc/test/node/ipc.cp.test.ts index 2c3ef666c01..147a2be5131 100644 --- a/src/vs/base/parts/ipc/test/node/ipc.cp.test.ts +++ b/src/vs/base/parts/ipc/test/node/ipc.cp.test.ts @@ -5,7 +5,6 @@ import * as assert from 'assert'; import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; -import { always } from 'vs/base/common/async'; import { TestServiceClient } from './testService'; import { getPathFromAmdModule } from 'vs/base/common/amd'; @@ -27,7 +26,7 @@ suite('IPC, Child Process', () => { assert.equal(r.outgoing, 'pong'); }); - return always(result, () => client.dispose()); + return result.finally(() => client.dispose()); }); test('events', () => { @@ -49,7 +48,7 @@ suite('IPC, Child Process', () => { const request = service.marco(); const result = Promise.all([request, event]); - return always(result, () => client.dispose()); + return result.finally(() => client.dispose()); }); test('event dispose', () => { @@ -74,6 +73,6 @@ suite('IPC, Child Process', () => { assert.equal(count, 2); }); - return always(result, () => client.dispose()); + return result.finally(() => client.dispose()); }); }); diff --git a/src/vs/base/parts/ipc/test/node/ipc.net.test.ts b/src/vs/base/parts/ipc/test/node/ipc.net.test.ts index 439dce11f52..957329d032b 100644 --- a/src/vs/base/parts/ipc/test/node/ipc.net.test.ts +++ b/src/vs/base/parts/ipc/test/node/ipc.net.test.ts @@ -6,68 +6,148 @@ import * as assert from 'assert'; import { Socket } from 'net'; import { EventEmitter } from 'events'; -import { Protocol } from 'vs/base/parts/ipc/node/ipc.net'; +import { Protocol, PersistentProtocol } from 'vs/base/parts/ipc/common/ipc.net'; +import { NodeSocket } from 'vs/base/parts/ipc/node/ipc.net'; +import { VSBuffer } from 'vs/base/common/buffer'; -class MockDuplex extends EventEmitter { +class MessageStream { - private _cache: Buffer[] = []; + private _currentComplete: ((data: VSBuffer) => void) | null; + private _messages: VSBuffer[]; - readonly destroyed = false; + constructor(x: Protocol | PersistentProtocol) { + this._currentComplete = null; + this._messages = []; + x.onMessage(data => { + this._messages.push(data); + this._trigger(); + }); + } - private _deliver(): void { - if (this._cache.length) { - const data = Buffer.concat(this._cache); - this._cache.length = 0; - this.emit('data', data); + private _trigger(): void { + if (!this._currentComplete) { + return; } + if (this._messages.length === 0) { + return; + } + const complete = this._currentComplete; + const msg = this._messages.shift()!; + + this._currentComplete = null; + complete(msg); + } + + public waitForOne(): Promise { + return new Promise((complete) => { + this._currentComplete = complete; + this._trigger(); + }); + } +} + +class EtherStream extends EventEmitter { + constructor( + private readonly _ether: Ether, + private readonly _name: 'a' | 'b' + ) { + super(); } write(data: Buffer, cb?: Function): boolean { - this._cache.push(data); - setImmediate(() => this._deliver()); + if (!Buffer.isBuffer(data)) { + throw new Error(`Invalid data`); + } + this._ether.write(this._name, data); return true; } } +class Ether { + + private readonly _a: EtherStream; + private readonly _b: EtherStream; + + private _ab: Buffer[]; + private _ba: Buffer[]; + + public get a(): Socket { + return this._a; + } + + public get b(): Socket { + return this._b; + } + + constructor() { + this._a = new EtherStream(this, 'a'); + this._b = new EtherStream(this, 'b'); + this._ab = []; + this._ba = []; + } + + public write(from: 'a' | 'b', data: Buffer): void { + if (from === 'a') { + this._ab.push(data); + } else { + this._ba.push(data); + } + + setImmediate(() => this._deliver()); + } + + private _deliver(): void { + + if (this._ab.length > 0) { + const data = Buffer.concat(this._ab); + this._ab.length = 0; + this._b.emit('data', data); + setImmediate(() => this._deliver()); + return; + } + + if (this._ba.length > 0) { + const data = Buffer.concat(this._ba); + this._ba.length = 0; + this._a.emit('data', data); + setImmediate(() => this._deliver()); + return; + } + + } +} suite('IPC, Socket Protocol', () => { - let stream: Socket; + let ether: Ether; setup(() => { - stream = new MockDuplex(); + ether = new Ether(); }); test('read/write', async () => { - const a = new Protocol(stream); - const b = new Protocol(stream); + const a = new Protocol(new NodeSocket(ether.a)); + const b = new Protocol(new NodeSocket(ether.b)); + const bMessages = new MessageStream(b); - await new Promise(resolve => { - const sub = b.onMessage(data => { - sub.dispose(); - assert.equal(data.toString(), 'foobarfarboo'); - resolve(undefined); - }); - a.send(Buffer.from('foobarfarboo')); - }); - return new Promise(resolve => { - const sub_1 = b.onMessage(data => { - sub_1.dispose(); - assert.equal(data.readInt8(0), 123); - resolve(undefined); - }); - const buffer = Buffer.allocUnsafe(1); - buffer.writeInt8(123, 0); - a.send(buffer); - }); + a.send(VSBuffer.fromString('foobarfarboo')); + const msg1 = await bMessages.waitForOne(); + assert.equal(msg1.toString(), 'foobarfarboo'); + + const buffer = VSBuffer.alloc(1); + buffer.writeUInt8(123, 0); + a.send(buffer); + const msg2 = await bMessages.waitForOne(); + assert.equal(msg2.readUInt8(0), 123); }); - test('read/write, object data', () => { + test('read/write, object data', async () => { - const a = new Protocol(stream); - const b = new Protocol(stream); + const a = new Protocol(new NodeSocket(ether.a)); + const b = new Protocol(new NodeSocket(ether.b)); + const bMessages = new MessageStream(b); const data = { pi: Math.PI, @@ -76,48 +156,69 @@ suite('IPC, Socket Protocol', () => { data: 'Hello World'.split('') }; - a.send(Buffer.from(JSON.stringify(data))); - - return new Promise(resolve => { - b.onMessage(msg => { - assert.deepEqual(JSON.parse(msg.toString()), data); - resolve(undefined); - }); - }); + a.send(VSBuffer.fromString(JSON.stringify(data))); + const msg = await bMessages.waitForOne(); + assert.deepEqual(JSON.parse(msg.toString()), data); }); - test('can devolve to a socket and evolve again without losing data', () => { - let resolve: (v: void) => void; - let result = new Promise((_resolve, _reject) => { - resolve = _resolve; - }); - const sender = new Protocol(stream); - const receiver1 = new Protocol(stream); +}); - assert.equal(stream.listenerCount('data'), 2); - assert.equal(stream.listenerCount('end'), 2); +suite('PersistentProtocol reconnection', () => { + let ether: Ether; - receiver1.onMessage((msg) => { - assert.equal(JSON.parse(msg.toString()).value, 1); + setup(() => { + ether = new Ether(); + }); - let buffer = receiver1.getBuffer(); - receiver1.dispose(); + test('acks get piggybacked with messages', async () => { + const a = new PersistentProtocol(new NodeSocket(ether.a)); + const aMessages = new MessageStream(a); + const b = new PersistentProtocol(new NodeSocket(ether.b)); + const bMessages = new MessageStream(b); - assert.equal(stream.listenerCount('data'), 1); - assert.equal(stream.listenerCount('end'), 1); + a.send(VSBuffer.fromString('a1')); + assert.equal(a.unacknowledgedCount, 1); + assert.equal(b.unacknowledgedCount, 0); - const receiver2 = new Protocol(stream, buffer); - receiver2.onMessage((msg) => { - assert.equal(JSON.parse(msg.toString()).value, 2); - resolve(undefined); - }); - }); + a.send(VSBuffer.fromString('a2')); + assert.equal(a.unacknowledgedCount, 2); + assert.equal(b.unacknowledgedCount, 0); - const msg1 = { value: 1 }; - const msg2 = { value: 2 }; - sender.send(Buffer.from(JSON.stringify(msg1))); - sender.send(Buffer.from(JSON.stringify(msg2))); + a.send(VSBuffer.fromString('a3')); + assert.equal(a.unacknowledgedCount, 3); + assert.equal(b.unacknowledgedCount, 0); - return result; + const a1 = await bMessages.waitForOne(); + assert.equal(a1.toString(), 'a1'); + assert.equal(a.unacknowledgedCount, 3); + assert.equal(b.unacknowledgedCount, 0); + + const a2 = await bMessages.waitForOne(); + assert.equal(a2.toString(), 'a2'); + assert.equal(a.unacknowledgedCount, 3); + assert.equal(b.unacknowledgedCount, 0); + + const a3 = await bMessages.waitForOne(); + assert.equal(a3.toString(), 'a3'); + assert.equal(a.unacknowledgedCount, 3); + assert.equal(b.unacknowledgedCount, 0); + + b.send(VSBuffer.fromString('b1')); + assert.equal(a.unacknowledgedCount, 3); + assert.equal(b.unacknowledgedCount, 1); + + const b1 = await aMessages.waitForOne(); + assert.equal(b1.toString(), 'b1'); + assert.equal(a.unacknowledgedCount, 0); + assert.equal(b.unacknowledgedCount, 1); + + a.send(VSBuffer.fromString('a4')); + assert.equal(a.unacknowledgedCount, 1); + assert.equal(b.unacknowledgedCount, 1); + + const b2 = await bMessages.waitForOne(); + assert.equal(b2.toString(), 'a4'); + assert.equal(a.unacknowledgedCount, 1); + assert.equal(b.unacknowledgedCount, 0); }); }); diff --git a/src/vs/base/parts/ipc/test/node/ipc.test.ts b/src/vs/base/parts/ipc/test/node/ipc.test.ts index 625f1a65922..14f059f5e08 100644 --- a/src/vs/base/parts/ipc/test/node/ipc.test.ts +++ b/src/vs/base/parts/ipc/test/node/ipc.test.ts @@ -4,18 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient, IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc'; +import { IChannel, IServerChannel, IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient } 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'; import { timeout } from 'vs/base/common/async'; +import { VSBuffer } from 'vs/base/common/buffer'; class QueueProtocol implements IMessagePassingProtocol { private buffering = true; - private buffers: Buffer[] = []; + private buffers: VSBuffer[] = []; - private _onMessage = new Emitter({ + private _onMessage = new Emitter({ onFirstListenerDidAdd: () => { for (const buffer of this.buffers) { this._onMessage.fire(buffer); @@ -32,11 +33,11 @@ class QueueProtocol implements IMessagePassingProtocol { readonly onMessage = this._onMessage.event; other: QueueProtocol; - send(buffer: Buffer): void { + send(buffer: VSBuffer): void { this.other.receive(buffer); } - protected receive(buffer: Buffer): void { + protected receive(buffer: VSBuffer): void { if (this.buffering) { this.buffers.push(buffer); } else { @@ -71,7 +72,7 @@ class TestIPCClient extends IPCClient { class TestIPCServer extends IPCServer { - private onDidClientConnect: Emitter; + private readonly onDidClientConnect: Emitter; constructor() { const onDidClientConnect = new Emitter(); @@ -142,7 +143,7 @@ class TestChannel implements IServerChannel { constructor(private service: ITestService) { } - call(_, command: string, arg: any, cancellationToken: CancellationToken): Promise { + call(_: unknown, command: string, arg: any, cancellationToken: CancellationToken): Promise { switch (command) { case 'marco': return this.service.marco(); case 'error': return this.service.error(arg); @@ -153,7 +154,7 @@ class TestChannel implements IServerChannel { } } - listen(_, event: string, arg?: any): Event { + listen(_: unknown, event: string, arg?: any): Event { switch (event) { case 'pong': return this.service.pong; default: throw new Error('not implemented'); @@ -195,10 +196,10 @@ suite('Base IPC', function () { test('createProtocolPair', async function () { const [clientProtocol, serverProtocol] = createProtocolPair(); - const b1 = Buffer.alloc(0); + const b1 = VSBuffer.alloc(0); clientProtocol.send(b1); - const b3 = Buffer.alloc(0); + const b3 = VSBuffer.alloc(0); serverProtocol.send(b3); const b2 = await Event.toPromise(serverProtocol.onMessage); diff --git a/src/vs/base/parts/ipc/test/node/testService.ts b/src/vs/base/parts/ipc/test/node/testService.ts index 6c35db5e4ea..6784bdfc60d 100644 --- a/src/vs/base/parts/ipc/test/node/testService.ts +++ b/src/vs/base/parts/ipc/test/node/testService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc'; +import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; import { Event, Emitter } from 'vs/base/common/event'; import { timeout } from 'vs/base/common/async'; @@ -41,7 +41,7 @@ export class TestChannel implements IServerChannel { constructor(private testService: ITestService) { } - listen(_, event: string): Event { + listen(_: unknown, event: string): Event { switch (event) { case 'marco': return this.testService.onMarco; } @@ -49,7 +49,7 @@ export class TestChannel implements IServerChannel { throw new Error('Event not found'); } - call(_, command: string, ...args: any[]): Promise { + call(_: unknown, command: string, ...args: any[]): Promise { switch (command) { case 'pong': return this.testService.pong(args[0]); case 'cancelMe': return this.testService.cancelMe(); diff --git a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts index e2081d58429..165db403b5d 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts @@ -8,8 +8,8 @@ import * as types from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { ITree, IActionProvider } from 'vs/base/parts/tree/browser/tree'; import { IconLabel, IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel'; -import { IQuickNavigateConfiguration, IModel, IDataSource, IFilter, IAccessiblityProvider, IRenderer, IRunner, Mode } from 'vs/base/parts/quickopen/common/quickOpen'; -import { Action, IAction, IActionRunner } from 'vs/base/common/actions'; +import { IQuickNavigateConfiguration, IModel, IDataSource, IFilter, IAccessiblityProvider, IRenderer, IRunner, Mode, IEntryRunContext } from 'vs/base/parts/quickopen/common/quickOpen'; +import { IAction, IActionRunner } from 'vs/base/common/actions'; import { compareAnything } from 'vs/base/common/comparers'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; @@ -35,15 +35,15 @@ let IDS = 0; export class QuickOpenItemAccessorClass implements IItemAccessor { - getItemLabel(entry: QuickOpenEntry): string { - return entry.getLabel(); + getItemLabel(entry: QuickOpenEntry): string | null { + return types.withUndefinedAsNull(entry.getLabel()); } - getItemDescription(entry: QuickOpenEntry): string { - return entry.getDescription(); + getItemDescription(entry: QuickOpenEntry): string | null { + return types.withUndefinedAsNull(entry.getDescription()); } - getItemPath(entry: QuickOpenEntry): string { + getItemPath(entry: QuickOpenEntry): string | undefined { const resource = entry.getResource(); return resource ? resource.fsPath : undefined; @@ -55,8 +55,8 @@ export const QuickOpenItemAccessor = new QuickOpenItemAccessorClass(); export class QuickOpenEntry { private id: string; private labelHighlights: IHighlight[]; - private descriptionHighlights: IHighlight[]; - private detailHighlights: IHighlight[]; + private descriptionHighlights?: IHighlight[]; + private detailHighlights?: IHighlight[]; private hidden: boolean; constructor(highlights: IHighlight[] = []) { @@ -75,15 +75,15 @@ export class QuickOpenEntry { /** * The label of the entry to identify it from others in the list */ - getLabel(): string { - return null; + getLabel(): string | undefined { + return undefined; } /** * The options for the label to use for this entry */ - getLabelOptions(): IIconLabelValueOptions { - return null; + getLabelOptions(): IIconLabelValueOptions | undefined { + return undefined; } /** @@ -97,51 +97,51 @@ export class QuickOpenEntry { /** * Detail information about the entry that is optional and can be shown below the label */ - getDetail(): string { - return null; + getDetail(): string | undefined { + return undefined; } /** * The icon of the entry to identify it from others in the list */ - getIcon(): string { - return null; + getIcon(): string | undefined { + return undefined; } /** * A secondary description that is optional and can be shown right to the label */ - getDescription(): string { - return null; + getDescription(): string | undefined { + return undefined; } /** * A tooltip to show when hovering over the entry. */ - getTooltip(): string { - return null; + getTooltip(): string | undefined { + return undefined; } /** * A tooltip to show when hovering over the description portion of the entry. */ - getDescriptionTooltip(): string { - return null; + getDescriptionTooltip(): string | undefined { + return undefined; } /** * An optional keybinding to show for an entry. */ - getKeybinding(): ResolvedKeybinding { - return null; + getKeybinding(): ResolvedKeybinding | undefined { + return undefined; } /** * A resource for this entry. Resource URIs can be used to compare different kinds of entries and group * them together. */ - getResource(): URI { - return null; + getResource(): URI | undefined { + return undefined; } /** @@ -170,7 +170,7 @@ export class QuickOpenEntry { /** * Allows to return highlight ranges that should show up for the entry label and description. */ - getHighlights(): [IHighlight[] /* Label */, IHighlight[] /* Description */, IHighlight[] /* Detail */] { + getHighlights(): [IHighlight[] /* Label */, IHighlight[] | undefined /* Description */, IHighlight[] | undefined /* Detail */] { return [this.labelHighlights, this.descriptionHighlights, this.detailHighlights]; } @@ -180,7 +180,7 @@ export class QuickOpenEntry { * * The context parameter provides additional context information how the run was triggered. */ - run(mode: Mode, context: IContext): boolean { + run(mode: Mode, context: IEntryRunContext): boolean { return false; } @@ -195,9 +195,9 @@ export class QuickOpenEntry { } export class QuickOpenEntryGroup extends QuickOpenEntry { - private entry: QuickOpenEntry; - private groupLabel: string; - private withBorder: boolean; + private entry?: QuickOpenEntry; + private groupLabel?: string; + private withBorder?: boolean; constructor(entry?: QuickOpenEntry, groupLabel?: string, withBorder?: boolean) { super(); @@ -210,11 +210,11 @@ export class QuickOpenEntryGroup extends QuickOpenEntry { /** * The label of the group or null if none. */ - getGroupLabel(): string { + getGroupLabel(): string | undefined { return this.groupLabel; } - setGroupLabel(groupLabel: string): void { + setGroupLabel(groupLabel: string | undefined): void { this.groupLabel = groupLabel; } @@ -222,18 +222,18 @@ export class QuickOpenEntryGroup extends QuickOpenEntry { * Whether to show a border on top of the group entry or not. */ showBorder(): boolean { - return this.withBorder; + return !!this.withBorder; } setShowBorder(showBorder: boolean): void { this.withBorder = showBorder; } - getLabel(): string { + getLabel(): string | undefined { return this.entry ? this.entry.getLabel() : super.getLabel(); } - getLabelOptions(): IIconLabelValueOptions { + getLabelOptions(): IIconLabelValueOptions | undefined { return this.entry ? this.entry.getLabelOptions() : super.getLabelOptions(); } @@ -241,27 +241,27 @@ export class QuickOpenEntryGroup extends QuickOpenEntry { return this.entry ? this.entry.getAriaLabel() : super.getAriaLabel(); } - getDetail(): string { + getDetail(): string | undefined { return this.entry ? this.entry.getDetail() : super.getDetail(); } - getResource(): URI { + getResource(): URI | undefined { return this.entry ? this.entry.getResource() : super.getResource(); } - getIcon(): string { + getIcon(): string | undefined { return this.entry ? this.entry.getIcon() : super.getIcon(); } - getDescription(): string { + getDescription(): string | undefined { return this.entry ? this.entry.getDescription() : super.getDescription(); } - getEntry(): QuickOpenEntry { + getEntry(): QuickOpenEntry | undefined { return this.entry; } - getHighlights(): [IHighlight[], IHighlight[], IHighlight[]] { + getHighlights(): [IHighlight[], IHighlight[] | undefined, IHighlight[] | undefined] { return this.entry ? this.entry.getHighlights() : super.getHighlights(); } @@ -277,7 +277,7 @@ export class QuickOpenEntryGroup extends QuickOpenEntry { this.entry ? this.entry.setHidden(hidden) : super.setHidden(hidden); } - run(mode: Mode, context: IContext): boolean { + run(mode: Mode, context: IEntryRunContext): boolean { return this.entry ? this.entry.run(mode, context) : super.run(mode, context); } } @@ -288,19 +288,7 @@ class NoActionProvider implements IActionProvider { return false; } - getActions(tree: ITree, element: any): IAction[] { - return null; - } - - hasSecondaryActions(tree: ITree, element: any): boolean { - return false; - } - - getSecondaryActions(tree: ITree, element: any): IAction[] { - return null; - } - - getActionItem(tree: ITree, element: any, action: Action) { + getActions(tree: ITree, element: any): IAction[] | null { return null; } } @@ -316,7 +304,7 @@ export interface IQuickOpenEntryTemplateData { } export interface IQuickOpenEntryGroupTemplateData extends IQuickOpenEntryTemplateData { - group: HTMLDivElement; + group?: HTMLDivElement; } const templateEntry = 'quickOpenEntry'; @@ -325,9 +313,9 @@ const templateEntryGroup = 'quickOpenEntryGroup'; class Renderer implements IRenderer { private actionProvider: IActionProvider; - private actionRunner: IActionRunner; + private actionRunner?: IActionRunner; - constructor(actionProvider: IActionProvider = new NoActionProvider(), actionRunner: IActionRunner | null = null) { + constructor(actionProvider: IActionProvider = new NoActionProvider(), actionRunner?: IActionRunner) { this.actionProvider = actionProvider; this.actionRunner = actionRunner; } @@ -356,7 +344,7 @@ class Renderer implements IRenderer { // Entry const row1 = DOM.$('.quick-open-row'); const row2 = DOM.$('.quick-open-row'); - const entry = DOM.$('.quick-open-entry', null, row1, row2); + const entry = DOM.$('.quick-open-entry', undefined, row1, row2); entryContainer.appendChild(entry); // Icon @@ -379,7 +367,7 @@ class Renderer implements IRenderer { const detail = new HighlightedLabel(detailContainer, true); // Entry Group - let group: HTMLDivElement; + let group: HTMLDivElement | undefined; if (templateId === templateEntryGroup) { group = document.createElement('div'); DOM.addClass(group, 'results-group'); @@ -442,7 +430,9 @@ class Renderer implements IRenderer { // Border if (group.showBorder()) { DOM.addClass(groupData.container, 'results-group-separator'); - groupData.container.style.borderTopColor = styles.pickerGroupBorder.toString(); + if (styles.pickerGroupBorder) { + groupData.container.style.borderTopColor = styles.pickerGroupBorder.toString(); + } } else { DOM.removeClass(groupData.container, 'results-group-separator'); groupData.container.style.borderTopColor = null; @@ -450,8 +440,12 @@ class Renderer implements IRenderer { // Group Label const groupLabel = group.getGroupLabel() || ''; - groupData.group.textContent = groupLabel; - groupData.group.style.color = styles.pickerGroupForeground.toString(); + if (groupData.group) { + groupData.group.textContent = groupLabel; + if (styles.pickerGroupForeground) { + groupData.group.style.color = styles.pickerGroupForeground.toString(); + } + } } // Normal Entry @@ -468,30 +462,27 @@ class Renderer implements IRenderer { options.title = entry.getTooltip(); options.descriptionTitle = entry.getDescriptionTooltip() || entry.getDescription(); // tooltip over description because it could overflow options.descriptionMatches = descriptionHighlights || []; - data.label.setLabel(entry.getLabel(), entry.getDescription(), options); + data.label.setLabel(types.withNullAsUndefined(entry.getLabel()), entry.getDescription(), options); // Meta data.detail.set(entry.getDetail(), detailHighlights); // Keybinding - data.keybinding.set(entry.getKeybinding(), null); + data.keybinding.set(entry.getKeybinding()!); } } disposeTemplate(templateId: string, templateData: IQuickOpenEntryGroupTemplateData): void { - const data = templateData as IQuickOpenEntryGroupTemplateData; - data.actionBar.dispose(); - data.actionBar = null; - data.container = null; - data.entry = null; - data.keybinding.dispose(); - data.keybinding = null; - data.detail.dispose(); - data.detail = null; - data.group = null; - data.icon = null; - data.label.dispose(); - data.label = null; + templateData.actionBar.dispose(); + templateData.actionBar = null!; + templateData.container = null!; + templateData.entry = null!; + templateData.keybinding = null!; + templateData.detail = null!; + templateData.group = null!; + templateData.icon = null!; + templateData.label.dispose(); + templateData.label = null!; } } @@ -564,8 +555,8 @@ export class QuickOpenModel implements return entry.getId(); } - getLabel(entry: QuickOpenEntry): string { - return entry.getLabel(); + getLabel(entry: QuickOpenEntry): string | null { + return types.withUndefinedAsNull(entry.getLabel()); } getAriaLabel(entry: QuickOpenEntry): string { @@ -581,7 +572,7 @@ export class QuickOpenModel implements return !entry.isHidden(); } - run(entry: QuickOpenEntry, mode: Mode, context: IContext): boolean { + run(entry: QuickOpenEntry, mode: Mode, context: IEntryRunContext): boolean { return entry.run(mode, context); } } @@ -605,8 +596,8 @@ export function compareEntries(elementA: QuickOpenEntry, elementB: QuickOpenEntr } // Fallback to the full path if labels are identical and we have associated resources - let nameA = elementA.getLabel(); - let nameB = elementB.getLabel(); + let nameA = elementA.getLabel()!; + let nameB = elementB.getLabel()!; if (nameA === nameB) { const resourceA = elementA.getResource(); const resourceB = elementB.getResource(); diff --git a/src/vs/base/parts/quickopen/browser/quickOpenViewer.ts b/src/vs/base/parts/quickopen/browser/quickOpenViewer.ts index 042d649f924..a87b30dbadc 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenViewer.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenViewer.ts @@ -24,7 +24,7 @@ export class DataSource implements IDataSource { getId(tree: ITree, element: any): string { if (!element) { - return null; + return null!; } const model = this.modelProvider.getModel(); @@ -33,7 +33,7 @@ export class DataSource implements IDataSource { hasChildren(tree: ITree, element: any): boolean { const model = this.modelProvider.getModel(); - return model && model === element && model.entries.length > 0; + return !!(model && model === element && model.entries.length > 0); } getChildren(tree: ITree, element: any): Promise { @@ -49,10 +49,10 @@ export class DataSource implements IDataSource { export class AccessibilityProvider implements IAccessibilityProvider { constructor(private modelProvider: IModelProvider) { } - getAriaLabel(tree: ITree, element: any): string { + getAriaLabel(tree: ITree, element: any): string | null { const model = this.modelProvider.getModel(); - return model.accessibilityProvider && model.accessibilityProvider.getAriaLabel(element); + return model.accessibilityProvider ? model.accessibilityProvider.getAriaLabel(element) : null; } getPosInSet(tree: ITree, element: any): string { diff --git a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts index 65cdc14af54..74148e4a0fd 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts @@ -36,7 +36,7 @@ export interface IQuickOpenCallbacks { export interface IQuickOpenOptions extends IQuickOpenStyles { minItemsToShow?: number; maxItemsToShow?: number; - inputPlaceHolder: string; + inputPlaceHolder?: string; inputAriaLabel?: string; actionProvider?: IActionProvider; keyboardSupport?: boolean; @@ -110,12 +110,12 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { private visible: boolean; private isLoosingFocus: boolean; private callbacks: IQuickOpenCallbacks; - private quickNavigateConfiguration: IQuickNavigateConfiguration; + private quickNavigateConfiguration: IQuickNavigateConfiguration | undefined; private container: HTMLElement; private treeElement: HTMLElement; private inputElement: HTMLElement; private layoutDimensions: DOM.Dimension; - private model: IModel; + private model: IModel | null; private inputChangingTimeoutHandle: any; private styles: IQuickOpenStyles; private renderer: Renderer; @@ -137,7 +137,7 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { } getModel(): IModel { - return this.model; + return this.model!; } setCallbacks(callbacks: IQuickOpenCallbacks): void { @@ -181,7 +181,7 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { DOM.addClass(this.inputContainer, 'quick-open-input'); this.element.appendChild(this.inputContainer); - this.inputBox = this._register(new InputBox(this.inputContainer, null, { + this.inputBox = this._register(new InputBox(this.inputContainer, undefined, { placeholder: this.options.inputPlaceHolder || '', ariaLabel: DEFAULT_INPUT_ARIA_LABEL, inputBackground: this.styles.inputBackground, @@ -538,10 +538,15 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { } // ARIA - this.inputElement.setAttribute('aria-activedescendant', this.treeElement.getAttribute('aria-activedescendant')); + const arivaActiveDescendant = this.treeElement.getAttribute('aria-activedescendant'); + if (arivaActiveDescendant) { + this.inputElement.setAttribute('aria-activedescendant', arivaActiveDescendant); + } else { + this.inputElement.removeAttribute('aria-activedescendant'); + } const context: IEntryRunContext = { event: event, keymods: this.extractKeyMods(event), quickNavigateConfiguration: this.quickNavigateConfiguration }; - this.model.runner.run(value, Mode.PREVIEW, context); + this.model!.runner.run(value, Mode.PREVIEW, context); } private elementSelected(value: any, event?: any, preferredMode?: Mode): void { @@ -553,7 +558,7 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { const context: IEntryRunContext = { event, keymods: this.extractKeyMods(event), quickNavigateConfiguration: this.quickNavigateConfiguration }; - hide = this.model.runner.run(value, mode, context); + hide = this.model!.runner.run(value, mode, context); } // Hide if command was run successfully @@ -603,7 +608,7 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { if (types.isString(param)) { this.doShowWithPrefix(param); } else { - if (options.value) { + if (options && options.value) { this.restoreLastInput(options.value); } this.doShowWithInput(param, options && options.autoFocus ? options.autoFocus : {}); @@ -634,7 +639,7 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { this.setInput(input, autoFocus); } - private setInputAndLayout(input: IModel, autoFocus: IAutoFocus): void { + private setInputAndLayout(input: IModel, autoFocus?: IAutoFocus): void { this.treeContainer.style.height = `${this.getHeight(input)}px`; this.tree.setInput(null).then(() => { @@ -676,7 +681,7 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { const prefix = autoFocus.autoFocusPrefixMatch; const lowerCasePrefix = prefix.toLowerCase(); for (const entry of entries) { - const label = input.dataSource.getLabel(entry); + const label = input.dataSource.getLabel(entry) || ''; if (!caseSensitiveMatch && label.indexOf(prefix) === 0) { caseSensitiveMatch = entry; @@ -747,13 +752,13 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { // Indicate entries to tree this.tree.layout(); - const entries = input ? input.entries.filter(e => this.isElementVisible(input, e)) : []; + const entries = input ? input.entries!.filter(e => this.isElementVisible(input!, e)) : []; this.updateResultCount(entries.length); // Handle auto focus if (autoFocus) { if (entries.length) { - this.autoFocus(input, entries, autoFocus); + this.autoFocus(input!, entries, autoFocus); } } }); @@ -770,7 +775,7 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { let height = 0; - let preferredItemsHeight: number; + let preferredItemsHeight: number | undefined; if (this.layoutDimensions && this.layoutDimensions.height) { preferredItemsHeight = (this.layoutDimensions.height - 50 /* subtract height of input field (30px) and some spacing (drop shadow) to fit */) * 0.4 /* max 40% of screen */; } @@ -834,12 +839,12 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { } if (this.callbacks.onHide) { - this.callbacks.onHide(reason); + this.callbacks.onHide(reason!); } } getQuickNavigateConfiguration(): IQuickNavigateConfiguration { - return this.quickNavigateConfiguration; + return this.quickNavigateConfiguration!; } setPlaceHolder(placeHolder: string): void { @@ -868,7 +873,7 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { } } - setInput(input: IModel, autoFocus: IAutoFocus, ariaLabel?: string): void { + setInput(input: IModel, autoFocus?: IAutoFocus, ariaLabel?: string): void { if (!this.isVisible()) { return; } @@ -940,7 +945,7 @@ export class QuickOpenWidget extends Disposable implements IModelProvider { return this.inputBox; } - setExtraClass(clazz: string): void { + setExtraClass(clazz: string | null): void { const previousClass = this.element.getAttribute('quick-open-extra-class'); if (previousClass) { DOM.removeClasses(this.element, previousClass); diff --git a/src/vs/base/parts/quickopen/common/quickOpen.ts b/src/vs/base/parts/quickopen/common/quickOpen.ts index e6d87a0b0e7..dd39a215ef1 100644 --- a/src/vs/base/parts/quickopen/common/quickOpen.ts +++ b/src/vs/base/parts/quickopen/common/quickOpen.ts @@ -49,7 +49,7 @@ export const enum Mode { export interface IEntryRunContext { event: any; keymods: IKeyMods; - quickNavigateConfiguration: IQuickNavigateConfiguration; + quickNavigateConfiguration: IQuickNavigateConfiguration | undefined; } export interface IKeyMods { @@ -59,7 +59,7 @@ export interface IKeyMods { export interface IDataSource { getId(entry: T): string; - getLabel(entry: T): string; + getLabel(entry: T): string | null; } /** diff --git a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts index 9abbda5ac13..21cb08caace 100644 --- a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts +++ b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts @@ -5,7 +5,7 @@ import { compareAnything } from 'vs/base/common/comparers'; import { matchesPrefix, IMatch, matchesCamelCase, isUpper } from 'vs/base/common/filters'; -import { nativeSep } from 'vs/base/common/paths'; +import { sep } from 'vs/base/common/path'; import { isWindows, isLinux } from 'vs/base/common/platform'; import { stripWildcards, equalsIgnoreCase } from 'vs/base/common/strings'; import { CharCode } from 'vs/base/common/charCode'; @@ -156,7 +156,7 @@ function doScore(query: string, queryLower: string, queryLength: number, target: return [scores[queryLength * targetLength - 1], positions.reverse()]; } -function computeCharScore(queryCharAtIndex, queryLowerCharAtIndex, target: string, targetLower: string, targetIndex: number, matchesSequenceLength: number): number { +function computeCharScore(queryCharAtIndex: string, queryLowerCharAtIndex: string, target: string, targetLower: string, targetIndex: number, matchesSequenceLength: number): number { let score = 0; if (queryLowerCharAtIndex !== targetLower[targetIndex]) { @@ -285,17 +285,17 @@ export interface IItemAccessor { /** * Just the label of the item to score on. */ - getItemLabel(item: T): string; + getItemLabel(item: T): string | null; /** * The optional description of the item to score on. Can be null. */ - getItemDescription(item: T): string; + getItemDescription(item: T): string | null; /** * If the item is a file, the path of the file to score on. Can be null. */ - getItemPath(file: T): string; + getItemPath(file: T): string | undefined; } const PATH_IDENTITY_SCORE = 1 << 18; @@ -320,11 +320,11 @@ export function prepareQuery(original: string): IPreparedQuery { let value = stripWildcards(original).replace(/\s/g, ''); // get rid of all wildcards and whitespace if (isWindows) { - value = value.replace(/\//g, nativeSep); // Help Windows users to search for paths when using slash + value = value.replace(/\//g, sep); // Help Windows users to search for paths when using slash } const lowercase = value.toLowerCase(); - const containsPathSeparator = value.indexOf(nativeSep) >= 0; + const containsPathSeparator = value.indexOf(sep) >= 0; return { original, value, lowercase, containsPathSeparator }; } @@ -376,10 +376,10 @@ function createMatches(offsets: undefined | number[]): IMatch[] { return ret; } -function doScoreItem(label: string, description: string, path: string, query: IPreparedQuery, fuzzy: boolean): IItemScore { +function doScoreItem(label: string, description: string | null, path: string | undefined, query: IPreparedQuery, fuzzy: boolean): IItemScore { // 1.) treat identity matches on full path highest - if (path && isLinux ? query.original === path : equalsIgnoreCase(query.original, path)) { + if (path && (isLinux ? query.original === path : equalsIgnoreCase(query.original, path))) { return { score: PATH_IDENTITY_SCORE, labelMatch: [{ start: 0, end: label.length }], descriptionMatch: description ? [{ start: 0, end: description.length }] : undefined }; } @@ -410,7 +410,7 @@ function doScoreItem(label: string, description: string, path: string, query: IP if (description) { let descriptionPrefix = description; if (!!path) { - descriptionPrefix = `${description}${nativeSep}`; // assume this is a file path + descriptionPrefix = `${description}${sep}`; // assume this is a file path } const descriptionPrefixLength = descriptionPrefix.length; @@ -469,8 +469,8 @@ export function compareItemsByScore(itemA: T, itemB: T, query: IPreparedQuery return scoreA === LABEL_PREFIX_SCORE ? -1 : 1; } - const labelA = accessor.getItemLabel(itemA); - const labelB = accessor.getItemLabel(itemB); + const labelA = accessor.getItemLabel(itemA) || ''; + const labelB = accessor.getItemLabel(itemB) || ''; // prefer shorter names when both match on label prefix if (labelA.length !== labelB.length) { @@ -484,8 +484,8 @@ export function compareItemsByScore(itemA: T, itemB: T, query: IPreparedQuery return scoreA === LABEL_CAMELCASE_SCORE ? -1 : 1; } - const labelA = accessor.getItemLabel(itemA); - const labelB = accessor.getItemLabel(itemB); + const labelA = accessor.getItemLabel(itemA) || ''; + const labelB = accessor.getItemLabel(itemB) || ''; // prefer more compact camel case matches over longer const comparedByMatchLength = compareByMatchLength(itemScoreA.labelMatch, itemScoreB.labelMatch); @@ -592,8 +592,8 @@ function compareByMatchLength(matchesA?: IMatch[], matchesB?: IMatch[]): number export function fallbackCompare(itemA: T, itemB: T, query: IPreparedQuery, accessor: IItemAccessor): number { // check for label + description length and prefer shorter - const labelA = accessor.getItemLabel(itemA); - const labelB = accessor.getItemLabel(itemB); + const labelA = accessor.getItemLabel(itemA) || ''; + const labelB = accessor.getItemLabel(itemB) || ''; const descriptionA = accessor.getItemDescription(itemA); const descriptionB = accessor.getItemDescription(itemB); diff --git a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts index dd317811cee..548cc9489f0 100644 --- a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts +++ b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import * as scorer from 'vs/base/parts/quickopen/common/quickOpenScorer'; import { URI } from 'vs/base/common/uri'; -import { basename, dirname, nativeSep } from 'vs/base/common/paths'; +import { basename, dirname, sep } from 'vs/base/common/path'; import { isWindows } from 'vs/base/common/platform'; class ResourceAccessorClass implements scorer.IItemAccessor { @@ -515,11 +515,27 @@ suite('Quick Open Scorer', () => { let query = 'vscode'; - let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache, (r1, r2, query, ResourceAccessor) => -1)); + let res = [resourceA, resourceB].sort((r1, r2) => { + return compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache, (r1, r2, query, ResourceAccessor) => { + if (r1 as any /* TS fail */ === resourceA) { + return -1; + } + + return 1; + }); + }); assert.equal(res[0], resourceA); assert.equal(res[1], resourceB); - res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache, (r1, r2, query, ResourceAccessor) => -1)); + res = [resourceB, resourceA].sort((r1, r2) => { + return compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache, (r1, r2, query, ResourceAccessor) => { + if (r1 as any /* TS fail */ === resourceB) { + return -1; + } + + return 1; + }); + }); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); }); @@ -797,9 +813,9 @@ suite('Quick Open Scorer', () => { }); test('compareFilesByScore - avoid match scattering (bug #12095)', function () { - const resourceA = URI.file('src/vs/workbench/parts/files/common/explorerViewModel.ts'); - const resourceB = URI.file('src/vs/workbench/parts/files/browser/views/explorerView.ts'); - const resourceC = URI.file('src/vs/workbench/parts/files/browser/views/explorerViewer.ts'); + const resourceA = URI.file('src/vs/workbench/contrib/files/common/explorerViewModel.ts'); + const resourceB = URI.file('src/vs/workbench/contrib/files/browser/views/explorerView.ts'); + const resourceC = URI.file('src/vs/workbench/contrib/files/browser/views/explorerViewer.ts'); let query = 'filesexplorerview.ts'; @@ -815,6 +831,6 @@ suite('Quick Open Scorer', () => { assert.equal(scorer.prepareQuery('model Tester.ts').value, 'modelTester.ts'); assert.equal(scorer.prepareQuery('Model Tester.ts').lowercase, 'modeltester.ts'); assert.equal(scorer.prepareQuery('ModelTester.ts').containsPathSeparator, false); - assert.equal(scorer.prepareQuery('Model' + nativeSep + 'Tester.ts').containsPathSeparator, true); + assert.equal(scorer.prepareQuery('Model' + sep + 'Tester.ts').containsPathSeparator, true); }); }); \ No newline at end of file diff --git a/src/vs/base/parts/storage/common/storage.ts b/src/vs/base/parts/storage/common/storage.ts new file mode 100644 index 00000000000..03dedeca57f --- /dev/null +++ b/src/vs/base/parts/storage/common/storage.ts @@ -0,0 +1,318 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { Emitter, Event } from 'vs/base/common/event'; +import { ThrottledDelayer } from 'vs/base/common/async'; +import { isUndefinedOrNull } from 'vs/base/common/types'; + +export enum StorageHint { + + // A hint to the storage that the storage + // does not exist on disk yet. This allows + // the storage library to improve startup + // time by not checking the storage for data. + STORAGE_DOES_NOT_EXIST +} + +export interface IStorageOptions { + hint?: StorageHint; +} + +export interface IUpdateRequest { + insert?: Map; + delete?: Set; +} + +export interface IStorageItemsChangeEvent { + items: Map; +} + +export interface IStorageDatabase { + + readonly onDidChangeItemsExternal: Event; + + getItems(): Promise>; + updateItems(request: IUpdateRequest): Promise; + + close(recovery?: () => Map): Promise; +} + +export interface IStorage extends IDisposable { + + readonly items: Map; + readonly size: number; + readonly onDidChangeStorage: Event; + + init(): Promise; + + get(key: string, fallbackValue: string): string; + get(key: string, fallbackValue?: string): string | undefined; + + getBoolean(key: string, fallbackValue: boolean): boolean; + getBoolean(key: string, fallbackValue?: boolean): boolean | undefined; + + getNumber(key: string, fallbackValue: number): number; + getNumber(key: string, fallbackValue?: number): number | undefined; + + set(key: string, value: string | boolean | number | undefined | null): Promise; + delete(key: string): Promise; + + close(): Promise; +} + +enum StorageState { + None, + Initialized, + Closed +} + +export class Storage extends Disposable implements IStorage { + + private static readonly DEFAULT_FLUSH_DELAY = 100; + + private readonly _onDidChangeStorage: Emitter = this._register(new Emitter()); + readonly onDidChangeStorage: Event = this._onDidChangeStorage.event; + + private state = StorageState.None; + + private cache: Map = new Map(); + + private flushDelayer: ThrottledDelayer; + + private pendingDeletes: Set = new Set(); + private pendingInserts: Map = new Map(); + + constructor( + protected database: IStorageDatabase, + private options: IStorageOptions = Object.create(null) + ) { + super(); + + this.flushDelayer = this._register(new ThrottledDelayer(Storage.DEFAULT_FLUSH_DELAY)); + + this.registerListeners(); + } + + private registerListeners(): void { + this._register(this.database.onDidChangeItemsExternal(e => this.onDidChangeItemsExternal(e))); + } + + private onDidChangeItemsExternal(e: IStorageItemsChangeEvent): void { + // items that change external require us to update our + // caches with the values. we just accept the value and + // emit an event if there is a change. + e.items.forEach((value, key) => this.accept(key, value)); + } + + private accept(key: string, value: string): void { + if (this.state === StorageState.Closed) { + return; // Return early if we are already closed + } + + let changed = false; + + // Item got removed, check for deletion + if (isUndefinedOrNull(value)) { + changed = this.cache.delete(key); + } + + // Item got updated, check for change + else { + const currentValue = this.cache.get(key); + if (currentValue !== value) { + this.cache.set(key, value); + changed = true; + } + } + + // Signal to outside listeners + if (changed) { + this._onDidChangeStorage.fire(key); + } + } + + get items(): Map { + return this.cache; + } + + get size(): number { + return this.cache.size; + } + + async init(): Promise { + if (this.state !== StorageState.None) { + return Promise.resolve(); // either closed or already initialized + } + + this.state = StorageState.Initialized; + + if (this.options.hint === StorageHint.STORAGE_DOES_NOT_EXIST) { + // return early if we know the storage file does not exist. this is a performance + // optimization to not load all items of the underlying storage if we know that + // there can be no items because the storage does not exist. + return Promise.resolve(); + } + + this.cache = await this.database.getItems(); + } + + get(key: string, fallbackValue: string): string; + get(key: string, fallbackValue?: string): string | undefined; + get(key: string, fallbackValue?: string): string | undefined { + const value = this.cache.get(key); + + if (isUndefinedOrNull(value)) { + return fallbackValue; + } + + return value; + } + + getBoolean(key: string, fallbackValue: boolean): boolean; + getBoolean(key: string, fallbackValue?: boolean): boolean | undefined; + getBoolean(key: string, fallbackValue?: boolean): boolean | undefined { + const value = this.get(key); + + if (isUndefinedOrNull(value)) { + return fallbackValue; + } + + return value === 'true'; + } + + getNumber(key: string, fallbackValue: number): number; + getNumber(key: string, fallbackValue?: number): number | undefined; + getNumber(key: string, fallbackValue?: number): number | undefined { + const value = this.get(key); + + if (isUndefinedOrNull(value)) { + return fallbackValue; + } + + return parseInt(value, 10); + } + + set(key: string, value: string | boolean | number | null | undefined): Promise { + if (this.state === StorageState.Closed) { + return Promise.resolve(); // Return early if we are already closed + } + + // We remove the key for undefined/null values + if (isUndefinedOrNull(value)) { + return this.delete(key); + } + + // Otherwise, convert to String and store + const valueStr = String(value); + + // Return early if value already set + const currentValue = this.cache.get(key); + if (currentValue === valueStr) { + return Promise.resolve(); + } + + // Update in cache and pending + this.cache.set(key, valueStr); + this.pendingInserts.set(key, valueStr); + this.pendingDeletes.delete(key); + + // Event + this._onDidChangeStorage.fire(key); + + // Accumulate work by scheduling after timeout + return this.flushDelayer.trigger(() => this.flushPending()); + } + + delete(key: string): Promise { + if (this.state === StorageState.Closed) { + return Promise.resolve(); // Return early if we are already closed + } + + // Remove from cache and add to pending + const wasDeleted = this.cache.delete(key); + if (!wasDeleted) { + return Promise.resolve(); // Return early if value already deleted + } + + if (!this.pendingDeletes.has(key)) { + this.pendingDeletes.add(key); + } + + this.pendingInserts.delete(key); + + // Event + this._onDidChangeStorage.fire(key); + + // Accumulate work by scheduling after timeout + return this.flushDelayer.trigger(() => this.flushPending()); + } + + async close(): Promise { + if (this.state === StorageState.Closed) { + return Promise.resolve(); // return if already closed + } + + // Update state + this.state = StorageState.Closed; + + // Trigger new flush to ensure data is persisted and then close + // even if there is an error flushing. We must always ensure + // the DB is closed to avoid corruption. + // + // Recovery: we pass our cache over as recovery option in case + // the DB is not healthy. + try { + await this.flushDelayer.trigger(() => this.flushPending(), 0 /* as soon as possible */); + } catch (error) { + // Ignore + } + + await this.database.close(() => this.cache); + } + + private flushPending(): Promise { + if (this.pendingInserts.size === 0 && this.pendingDeletes.size === 0) { + return Promise.resolve(); // return early if nothing to do + } + + // Get pending data + const updateRequest: IUpdateRequest = { insert: this.pendingInserts, delete: this.pendingDeletes }; + + // Reset pending data for next run + this.pendingDeletes = new Set(); + this.pendingInserts = new Map(); + + // Update in storage + return this.database.updateItems(updateRequest); + } +} + +export class InMemoryStorageDatabase implements IStorageDatabase { + + readonly onDidChangeItemsExternal = Event.None; + + private items = new Map(); + + getItems(): Promise> { + return Promise.resolve(this.items); + } + + updateItems(request: IUpdateRequest): Promise { + if (request.insert) { + request.insert.forEach((value, key) => this.items.set(key, value)); + } + + if (request.delete) { + request.delete.forEach(key => this.items.delete(key)); + } + + return Promise.resolve(); + } + + close(): Promise { + return Promise.resolve(); + } +} \ No newline at end of file diff --git a/src/vs/base/parts/storage/node/storage.ts b/src/vs/base/parts/storage/node/storage.ts new file mode 100644 index 00000000000..6cebac12c9f --- /dev/null +++ b/src/vs/base/parts/storage/node/storage.ts @@ -0,0 +1,451 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Database, Statement } from 'vscode-sqlite3'; +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 { fill } from 'vs/base/common/arrays'; +import { IStorageDatabase, IStorageItemsChangeEvent, IUpdateRequest } from 'vs/base/parts/storage/common/storage'; + +interface IDatabaseConnection { + db: Database; + + isInMemory: boolean; + + isErroneous?: boolean; + lastError?: string; +} + +export interface ISQLiteStorageDatabaseOptions { + logging?: ISQLiteStorageDatabaseLoggingOptions; +} + +export interface ISQLiteStorageDatabaseLoggingOptions { + logError?: (error: string | Error) => void; + logTrace?: (msg: string) => void; +} + +export class SQLiteStorageDatabase implements IStorageDatabase { + + static IN_MEMORY_PATH = ':memory:'; + + get onDidChangeItemsExternal(): Event { return Event.None; } // since we are the only client, there can be no external changes + + private static BUSY_OPEN_TIMEOUT = 2000; // timeout in ms to retry when opening DB fails with SQLITE_BUSY + private static MAX_HOST_PARAMETERS = 256; // maximum number of parameters within a statement + + private path: string; + private name: string; + + private logger: SQLiteStorageDatabaseLogger; + + private whenConnected: Promise; + + constructor(path: string, options: ISQLiteStorageDatabaseOptions = Object.create(null)) { + this.path = path; + this.name = basename(path); + + this.logger = new SQLiteStorageDatabaseLogger(options.logging); + + this.whenConnected = this.connect(path); + } + + async getItems(): Promise> { + const connection = await this.whenConnected; + + const items = new Map(); + + const rows = await this.all(connection, 'SELECT * FROM ItemTable'); + rows.forEach(row => items.set(row.key, row.value)); + + if (this.logger.isTracing) { + this.logger.trace(`[storage ${this.name}] getItems(): ${items.size} rows`); + } + + return items; + } + + async updateItems(request: IUpdateRequest): Promise { + const connection = await this.whenConnected; + + return this.doUpdateItems(connection, request); + } + + private doUpdateItems(connection: IDatabaseConnection, request: IUpdateRequest): Promise { + if (this.logger.isTracing) { + this.logger.trace(`[storage ${this.name}] updateItems(): insert(${request.insert ? mapToString(request.insert) : '0'}), delete(${request.delete ? setToString(request.delete) : '0'})`); + } + + return this.transaction(connection, () => { + + // INSERT + if (request.insert && request.insert.size > 0) { + const keysValuesChunks: (string[])[] = []; + keysValuesChunks.push([]); // seed with initial empty chunk + + // Split key/values into chunks of SQLiteStorageDatabase.MAX_HOST_PARAMETERS + // so that we can efficiently run the INSERT with as many HOST parameters as possible + let currentChunkIndex = 0; + request.insert.forEach((value, key) => { + let keyValueChunk = keysValuesChunks[currentChunkIndex]; + + if (keyValueChunk.length > SQLiteStorageDatabase.MAX_HOST_PARAMETERS) { + currentChunkIndex++; + keyValueChunk = []; + keysValuesChunks.push(keyValueChunk); + } + + keyValueChunk.push(key, value); + }); + + keysValuesChunks.forEach(keysValuesChunk => { + this.prepare(connection, `INSERT INTO ItemTable VALUES ${fill(keysValuesChunk.length / 2, '(?,?)').join(',')}`, stmt => stmt.run(keysValuesChunk), () => { + const keys: string[] = []; + let length = 0; + request.insert!.forEach((value, key) => { + keys.push(key); + length += value.length; + }); + + return `Keys: ${keys.join(', ')} Length: ${length}`; + }); + }); + } + + // DELETE + if (request.delete && request.delete.size) { + const keysChunks: (string[])[] = []; + keysChunks.push([]); // seed with initial empty chunk + + // Split keys into chunks of SQLiteStorageDatabase.MAX_HOST_PARAMETERS + // so that we can efficiently run the DELETE with as many HOST parameters + // as possible + let currentChunkIndex = 0; + request.delete.forEach(key => { + let keyChunk = keysChunks[currentChunkIndex]; + + if (keyChunk.length > SQLiteStorageDatabase.MAX_HOST_PARAMETERS) { + currentChunkIndex++; + keyChunk = []; + keysChunks.push(keyChunk); + } + + keyChunk.push(key); + }); + + keysChunks.forEach(keysChunk => { + this.prepare(connection, `DELETE FROM ItemTable WHERE key IN (${fill(keysChunk.length, '?').join(',')})`, stmt => stmt.run(keysChunk), () => { + const keys: string[] = []; + request.delete!.forEach(key => { + keys.push(key); + }); + + return `Keys: ${keys.join(', ')}`; + }); + }); + } + }); + } + + async close(recovery?: () => Map): Promise { + this.logger.trace(`[storage ${this.name}] close()`); + + const connection = await this.whenConnected; + + return this.doClose(connection, recovery); + } + + private doClose(connection: IDatabaseConnection, recovery?: () => Map): Promise { + return new Promise((resolve, reject) => { + connection.db.close(closeError => { + if (closeError) { + this.handleSQLiteError(connection, closeError, `[storage ${this.name}] close(): ${closeError}`); + } + + // Return early if this storage was created only in-memory + // e.g. when running tests we do not need to backup. + if (this.path === SQLiteStorageDatabase.IN_MEMORY_PATH) { + return resolve(); + } + + // If the DB closed successfully and we are not running in-memory + // and the DB did not get errors during runtime, make a backup + // of the DB so that we can use it as fallback in case the actual + // DB becomes corrupt in the future. + if (!connection.isErroneous && !connection.isInMemory) { + return this.backup().then(resolve, error => { + this.logger.error(`[storage ${this.name}] backup(): ${error}`); + + return resolve(); // ignore failing backup + }); + } + + // Recovery: if we detected errors while using the DB or we are using + // an inmemory DB (as a fallback to not being able to open the DB initially) + // and we have a recovery function provided, we recreate the DB with this + // data to recover all known data without loss if possible. + if (typeof recovery === 'function') { + + // 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(() => { + + // Re-open the DB fresh + return this.doConnect(this.path).then(recoveryConnection => { + const closeRecoveryConnection = () => { + return this.doClose(recoveryConnection, undefined /* do not attempt to recover again */); + }; + + // Store items + return this.doUpdateItems(recoveryConnection, { insert: recovery() }).then(() => closeRecoveryConnection(), error => { + + // In case of an error updating items, still ensure to close the connection + // to prevent SQLITE_BUSY errors when the connection is restablished + closeRecoveryConnection(); + + return Promise.reject(error); + }); + }); + }).then(resolve, reject); + } + + // Finally without recovery we just reject + return reject(closeError || new Error('Database has errors or is in-memory without recovery option')); + }); + }); + } + + private backup(): Promise { + const backupPath = this.toBackupPath(this.path); + + return copy(this.path, backupPath); + } + + private toBackupPath(path: string): string { + return `${path}.backup`; + } + + async checkIntegrity(full: boolean): Promise { + this.logger.trace(`[storage ${this.name}] checkIntegrity(full: ${full})`); + + const connection = await this.whenConnected; + const row = await this.get(connection, full ? 'PRAGMA integrity_check' : 'PRAGMA quick_check'); + + const integrity = full ? (row as any)['integrity_check'] : (row as any)['quick_check']; + + if (connection.isErroneous) { + return `${integrity} (last error: ${connection.lastError})`; + } + + if (connection.isInMemory) { + return `${integrity} (in-memory!)`; + } + + return integrity; + } + + private async connect(path: string, retryOnBusy: boolean = true): Promise { + this.logger.trace(`[storage ${this.name}] open(${path}, retryOnBusy: ${retryOnBusy})`); + + try { + return await this.doConnect(path); + } catch (error) { + this.logger.error(`[storage ${this.name}] open(): Unable to open DB due to ${error}`); + + // SQLITE_BUSY should only arise if another process is locking the same DB we want + // to open at that time. This typically never happens because a DB connection is + // limited per window. However, in the event of a window reload, it may be possible + // that the previous connection was not properly closed while the new connection is + // already established. + // + // In this case we simply wait for some time and retry once to establish the connection. + // + if (error.code === 'SQLITE_BUSY' && retryOnBusy) { + await timeout(SQLiteStorageDatabase.BUSY_OPEN_TIMEOUT); + + return this.connect(path, false /* not another retry */); + } + + // Otherwise, best we can do is to recover from a backup if that exists, as such we + // move the DB to a different filename and try to load from backup. If that fails, + // a new empty DB is being created automatically. + // + // The final fallback is to use an in-memory DB which should only happen if the target + // folder is really not writeable for us. + // + try { + await unlink(path); + await renameIgnoreError(this.toBackupPath(path), path); + + return await this.doConnect(path); + } catch (error) { + this.logger.error(`[storage ${this.name}] open(): Unable to use backup due to ${error}`); + + // In case of any error to open the DB, use an in-memory + // DB so that we always have a valid DB to talk to. + return this.doConnect(SQLiteStorageDatabase.IN_MEMORY_PATH); + } + } + } + + private handleSQLiteError(connection: IDatabaseConnection, error: Error & { code?: string }, msg: string): void { + connection.isErroneous = true; + connection.lastError = msg; + + this.logger.error(msg); + } + + private doConnect(path: string): Promise { + return new Promise((resolve, reject) => { + import('vscode-sqlite3').then(sqlite3 => { + const connection: IDatabaseConnection = { + db: new (this.logger.isTracing ? sqlite3.verbose().Database : sqlite3.Database)(path, error => { + if (error) { + return connection.db ? connection.db.close(() => reject(error)) : reject(error); + } + + // The following exec() statement serves two purposes: + // - create the DB if it does not exist yet + // - validate that the DB is not corrupt (the open() call does not throw otherwise) + return this.exec(connection, [ + 'PRAGMA user_version = 1;', + 'CREATE TABLE IF NOT EXISTS ItemTable (key TEXT UNIQUE ON CONFLICT REPLACE, value BLOB)' + ].join('')).then(() => { + return resolve(connection); + }, error => { + return connection.db.close(() => reject(error)); + }); + }), + isInMemory: path === SQLiteStorageDatabase.IN_MEMORY_PATH + }; + + // Errors + connection.db.on('error', error => this.handleSQLiteError(connection, error, `[storage ${this.name}] Error (event): ${error}`)); + + // Tracing + if (this.logger.isTracing) { + connection.db.on('trace', sql => this.logger.trace(`[storage ${this.name}] Trace (event): ${sql}`)); + } + }, reject); + }); + } + + private exec(connection: IDatabaseConnection, sql: string): Promise { + return new Promise((resolve, reject) => { + connection.db.exec(sql, error => { + if (error) { + this.handleSQLiteError(connection, error, `[storage ${this.name}] exec(): ${error}`); + + return reject(error); + } + + return resolve(); + }); + }); + } + + private get(connection: IDatabaseConnection, sql: string): Promise { + return new Promise((resolve, reject) => { + connection.db.get(sql, (error, row) => { + if (error) { + this.handleSQLiteError(connection, error, `[storage ${this.name}] get(): ${error}`); + + return reject(error); + } + + return resolve(row); + }); + }); + } + + private all(connection: IDatabaseConnection, sql: string): Promise<{ key: string, value: string }[]> { + return new Promise((resolve, reject) => { + connection.db.all(sql, (error, rows) => { + if (error) { + this.handleSQLiteError(connection, error, `[storage ${this.name}] all(): ${error}`); + + return reject(error); + } + + return resolve(rows); + }); + }); + } + + private transaction(connection: IDatabaseConnection, transactions: () => void): Promise { + return new Promise((resolve, reject) => { + connection.db.serialize(() => { + connection.db.run('BEGIN TRANSACTION'); + + transactions(); + + connection.db.run('END TRANSACTION', error => { + if (error) { + this.handleSQLiteError(connection, error, `[storage ${this.name}] transaction(): ${error}`); + + return reject(error); + } + + return resolve(); + }); + }); + }); + } + + private prepare(connection: IDatabaseConnection, sql: string, runCallback: (stmt: Statement) => void, errorDetails: () => string): void { + const stmt = connection.db.prepare(sql); + + const statementErrorListener = (error: Error) => { + this.handleSQLiteError(connection, error, `[storage ${this.name}] prepare(): ${error} (${sql}). Details: ${errorDetails()}`); + }; + + stmt.on('error', statementErrorListener); + + runCallback(stmt); + + stmt.finalize(error => { + if (error) { + statementErrorListener(error); + } + + stmt.removeListener('error', statementErrorListener); + }); + } +} + +class SQLiteStorageDatabaseLogger { + private readonly logTrace: (msg: string) => void; + private readonly logError: (error: string | Error) => void; + + constructor(options?: ISQLiteStorageDatabaseLoggingOptions) { + if (options && typeof options.logTrace === 'function') { + this.logTrace = options.logTrace; + } + + if (options && typeof options.logError === 'function') { + this.logError = options.logError; + } + } + + get isTracing(): boolean { + return !!this.logTrace; + } + + trace(msg: string): void { + if (this.logTrace) { + this.logTrace(msg); + } + } + + error(error: string | Error): void { + if (this.logError) { + this.logError(error); + } + } +} diff --git a/src/vs/base/test/node/storage/storage.test.ts b/src/vs/base/parts/storage/test/node/storage.test.ts similarity index 86% rename from src/vs/base/test/node/storage/storage.test.ts rename to src/vs/base/parts/storage/test/node/storage.test.ts index 847fc67ad96..4c915ef2ae7 100644 --- a/src/vs/base/test/node/storage/storage.test.ts +++ b/src/vs/base/parts/storage/test/node/storage.test.ts @@ -3,14 +3,16 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Storage, SQLiteStorageDatabase, IStorageDatabase, ISQLiteStorageDatabaseOptions, IStorageItemsChangeEvent } from 'vs/base/node/storage'; +import { SQLiteStorageDatabase, ISQLiteStorageDatabaseOptions } from 'vs/base/parts/storage/node/storage'; +import { Storage, IStorageDatabase, IStorageItemsChangeEvent } from 'vs/base/parts/storage/common/storage'; import { generateUuid } from 'vs/base/common/uuid'; -import { join } from 'path'; +import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; import { equal, ok } from 'assert'; -import { mkdirp, del, writeFile } from 'vs/base/node/pfs'; +import { mkdirp, writeFile, exists, unlink, rimraf, RimRafMode } from 'vs/base/node/pfs'; import { timeout } from 'vs/base/common/async'; import { Event, Emitter } from 'vs/base/common/event'; +import { isWindows } from 'vs/base/common/platform'; suite('Storage Library', () => { @@ -30,7 +32,7 @@ suite('Storage Library', () => { // Empty fallbacks equal(storage.get('foo', 'bar'), 'bar'); - equal(storage.getInteger('foo', 55), 55); + equal(storage.getNumber('foo', 55), 55); equal(storage.getBoolean('foo', true), true); let changes = new Set(); @@ -44,7 +46,7 @@ suite('Storage Library', () => { const set3Promise = storage.set('barBoolean', true); equal(storage.get('bar'), 'foo'); - equal(storage.getInteger('barNumber'), 55); + equal(storage.getNumber('barNumber'), 55); equal(storage.getBoolean('barBoolean'), true); equal(changes.size, 3); @@ -70,7 +72,7 @@ suite('Storage Library', () => { const delete3Promise = storage.delete('barBoolean'); ok(!storage.get('bar')); - ok(!storage.getInteger('barNumber')); + ok(!storage.getNumber('barNumber')); ok(!storage.getBoolean('barBoolean')); equal(changes.size, 3); @@ -91,7 +93,7 @@ suite('Storage Library', () => { equal(deletePromiseResolved, true); await storage.close(); - await del(storageDir, tmpdir()); + await rimraf(storageDir, RimRafMode.MOVE); }); test('external changes', async () => { @@ -147,7 +149,7 @@ suite('Storage Library', () => { equal(changes.size, 0); await storage.close(); - await del(storageDir, tmpdir()); + await rimraf(storageDir, RimRafMode.MOVE); }); test('close flushes data', async () => { @@ -201,7 +203,7 @@ suite('Storage Library', () => { ok(!storage.get('bar')); await storage.close(); - await del(storageDir, tmpdir()); + await rimraf(storageDir, RimRafMode.MOVE); }); test('conflicting updates', async () => { @@ -243,7 +245,37 @@ suite('Storage Library', () => { ok(setAndDeletePromiseResolved); await storage.close(); - await del(storageDir, tmpdir()); + await rimraf(storageDir, RimRafMode.MOVE); + }); + + test('corrupt DB recovers', async () => { + const storageDir = uniqueStorageDir(); + await mkdirp(storageDir); + + const storageFile = join(storageDir, 'storage.db'); + + let storage = new Storage(new SQLiteStorageDatabase(storageFile)); + await storage.init(); + + await storage.set('bar', 'foo'); + + await writeFile(storageFile, 'This is a broken DB'); + + await storage.set('foo', 'bar'); + + equal(storage.get('bar'), 'foo'); + equal(storage.get('foo'), 'bar'); + + await storage.close(); + + storage = new Storage(new SQLiteStorageDatabase(storageFile)); + await storage.init(); + + equal(storage.get('bar'), 'foo'); + equal(storage.get('foo'), 'bar'); + + await storage.close(); + await rimraf(storageDir, RimRafMode.MOVE); }); }); @@ -262,7 +294,7 @@ suite('SQLite Storage Library', () => { return set; } - async function testDBBasics(path, logError?: (error) => void) { + async function testDBBasics(path: string, logError?: (error: Error) => void) { let options!: ISQLiteStorageDatabaseOptions; if (logError) { options = { @@ -324,7 +356,14 @@ suite('SQLite Storage Library', () => { storedItems = await storage.getItems(); equal(storedItems.size, 0); - await storage.close(); + let recoveryCalled = false; + await storage.close(() => { + recoveryCalled = true; + + return new Map(); + }); + + equal(recoveryCalled, false); } test('basics', async () => { @@ -332,9 +371,9 @@ suite('SQLite Storage Library', () => { await mkdirp(storageDir); - testDBBasics(join(storageDir, 'storage.db')); + await testDBBasics(join(storageDir, 'storage.db')); - await del(storageDir, tmpdir()); + await rimraf(storageDir, RimRafMode.MOVE); }); test('basics (open multiple times)', async () => { @@ -345,7 +384,7 @@ suite('SQLite Storage Library', () => { await testDBBasics(join(storageDir, 'storage.db')); await testDBBasics(join(storageDir, 'storage.db')); - await del(storageDir, tmpdir()); + await rimraf(storageDir, RimRafMode.MOVE); }); test('basics (corrupt DB falls back to empty DB)', async () => { @@ -363,7 +402,7 @@ suite('SQLite Storage Library', () => { ok(expectedError); - await del(storageDir, tmpdir()); + await rimraf(storageDir, RimRafMode.MOVE); }); test('basics (corrupt DB restores from previous backup)', async () => { @@ -392,9 +431,16 @@ suite('SQLite Storage Library', () => { equal(storedItems.get('some/foo/path'), 'some/bar/path'); equal(storedItems.get(JSON.stringify({ foo: 'bar' })), JSON.stringify({ bar: 'foo' })); - await storage.close(); + let recoveryCalled = false; + await storage.close(() => { + recoveryCalled = true; - await del(storageDir, tmpdir()); + return new Map(); + }); + + equal(recoveryCalled, false); + + await rimraf(storageDir, RimRafMode.MOVE); }); test('basics (corrupt DB falls back to empty DB if backup is corrupt)', async () => { @@ -423,10 +469,80 @@ suite('SQLite Storage Library', () => { await testDBBasics(storagePath); - await del(storageDir, tmpdir()); + await rimraf(storageDir, RimRafMode.MOVE); }); - test('real world example', async () => { + test('basics (DB that becomes corrupt during runtime stores all state from cache on close)', async () => { + if (isWindows) { + await Promise.resolve(); // Windows will fail to write to open DB due to locking + + return; + } + + const storageDir = uniqueStorageDir(); + + await mkdirp(storageDir); + + const storagePath = join(storageDir, 'storage.db'); + let storage = new SQLiteStorageDatabase(storagePath); + + const items = new Map(); + items.set('foo', 'bar'); + items.set('some/foo/path', 'some/bar/path'); + items.set(JSON.stringify({ foo: 'bar' }), JSON.stringify({ bar: 'foo' })); + + await storage.updateItems({ insert: items }); + await storage.close(); + + const backupPath = `${storagePath}.backup`; + equal(await exists(backupPath), true); + + storage = new SQLiteStorageDatabase(storagePath); + await storage.getItems(); + + await writeFile(storagePath, 'This is now a broken DB'); + + // we still need to trigger a check to the DB so that we get to know that + // the DB is corrupt. We have no extra code on shutdown that checks for the + // health of the DB. This is an optimization to not perform too many tasks + // on shutdown. + await storage.checkIntegrity(true).then(null, error => { } /* error is expected here but we do not want to fail */); + + await unlink(backupPath); // also test that the recovery DB is backed up properly + + let recoveryCalled = false; + await storage.close(() => { + recoveryCalled = true; + + return items; + }); + + equal(recoveryCalled, true); + equal(await exists(backupPath), true); + + storage = new SQLiteStorageDatabase(storagePath); + + const storedItems = await storage.getItems(); + equal(storedItems.size, items.size); + equal(storedItems.get('foo'), 'bar'); + equal(storedItems.get('some/foo/path'), 'some/bar/path'); + equal(storedItems.get(JSON.stringify({ foo: 'bar' })), JSON.stringify({ bar: 'foo' })); + + recoveryCalled = false; + await storage.close(() => { + recoveryCalled = true; + + return new Map(); + }); + + equal(recoveryCalled, false); + + await rimraf(storageDir, RimRafMode.MOVE); + }); + + test('real world example', async function () { + this.timeout(20000); + const storageDir = uniqueStorageDir(); await mkdirp(storageDir); @@ -440,7 +556,7 @@ suite('SQLite Storage Library', () => { items1.set('debug.actionswidgetposition', '0.6880952380952381'); const items2 = new Map(); - items2.set('workbench.editors.files.textfileeditor', '{"textEditorViewState":[["file:///Users/dummy/Documents/ticino-playground/play.htm",{"0":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":6,"column":16},"position":{"lineNumber":6,"column":16}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{},"editor.contrib.wordHighlighter":false}}}],["file:///Users/dummy/Documents/ticino-playground/nakefile.js",{"0":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":7,"column":81},"position":{"lineNumber":7,"column":81}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":20},"contributionsState":{"editor.contrib.folding":{},"editor.contrib.wordHighlighter":false}}}],["file:///Users/dummy/Desktop/vscode2/.gitattributes",{"0":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":9,"column":12},"position":{"lineNumber":9,"column":12}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":20},"contributionsState":{"editor.contrib.folding":{},"editor.contrib.wordHighlighter":false}}}],["file:///Users/dummy/Desktop/vscode2/src/vs/workbench/parts/search/browser/openAnythingHandler.ts",{"0":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{},"editor.contrib.wordHighlighter":false}}}]]}'); + items2.set('workbench.editors.files.textfileeditor', '{"textEditorViewState":[["file:///Users/dummy/Documents/ticino-playground/play.htm",{"0":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":6,"column":16},"position":{"lineNumber":6,"column":16}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{},"editor.contrib.wordHighlighter":false}}}],["file:///Users/dummy/Documents/ticino-playground/nakefile.js",{"0":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":7,"column":81},"position":{"lineNumber":7,"column":81}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":20},"contributionsState":{"editor.contrib.folding":{},"editor.contrib.wordHighlighter":false}}}],["file:///Users/dummy/Desktop/vscode2/.gitattributes",{"0":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":9,"column":12},"position":{"lineNumber":9,"column":12}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":20},"contributionsState":{"editor.contrib.folding":{},"editor.contrib.wordHighlighter":false}}}],["file:///Users/dummy/Desktop/vscode2/src/vs/workbench/contrib/search/browser/openAnythingHandler.ts",{"0":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{},"editor.contrib.wordHighlighter":false}}}]]}'); const items3 = new Map(); items3.set('nps/iscandidate', 'false'); @@ -512,10 +628,12 @@ suite('SQLite Storage Library', () => { await storage.close(); - await del(storageDir, tmpdir()); + await rimraf(storageDir, RimRafMode.MOVE); }); - test('very large item value', async () => { + test('very large item value', async function () { + this.timeout(20000); + const storageDir = uniqueStorageDir(); await mkdirp(storageDir); @@ -565,7 +683,7 @@ suite('SQLite Storage Library', () => { await storage.close(); - await del(storageDir, tmpdir()); + await rimraf(storageDir, RimRafMode.MOVE); }); test('multiple concurrent writes execute in sequence', async () => { @@ -622,6 +740,70 @@ suite('SQLite Storage Library', () => { await storage.close(); - await del(storageDir, tmpdir()); + await rimraf(storageDir, RimRafMode.MOVE); + }); + + test('lots of INSERT & DELETE (below inline max)', async () => { + const storageDir = uniqueStorageDir(); + + await mkdirp(storageDir); + + const storage = new SQLiteStorageDatabase(join(storageDir, 'storage.db')); + + const items = new Map(); + const keys: Set = new Set(); + for (let i = 0; i < 200; i++) { + const uuid = generateUuid(); + const key = `key: ${uuid}`; + + items.set(key, `value: ${uuid}`); + keys.add(key); + } + + await storage.updateItems({ insert: items }); + + let storedItems = await storage.getItems(); + equal(storedItems.size, items.size); + + await storage.updateItems({ delete: keys }); + + storedItems = await storage.getItems(); + equal(storedItems.size, 0); + + await storage.close(); + + await rimraf(storageDir, RimRafMode.MOVE); + }); + + test('lots of INSERT & DELETE (above inline max)', async () => { + const storageDir = uniqueStorageDir(); + + await mkdirp(storageDir); + + const storage = new SQLiteStorageDatabase(join(storageDir, 'storage.db')); + + const items = new Map(); + const keys: Set = new Set(); + for (let i = 0; i < 400; i++) { + const uuid = generateUuid(); + const key = `key: ${uuid}`; + + items.set(key, `value: ${uuid}`); + keys.add(key); + } + + await storage.updateItems({ insert: items }); + + let storedItems = await storage.getItems(); + equal(storedItems.size, items.size); + + await storage.updateItems({ delete: keys }); + + storedItems = await storage.getItems(); + equal(storedItems.size, 0); + + await storage.close(); + + await rimraf(storageDir, RimRafMode.MOVE); }); }); diff --git a/src/vs/base/parts/tree/browser/CollapseAll.svg b/src/vs/base/parts/tree/browser/CollapseAll.svg deleted file mode 100644 index 7d11a30f6e0..00000000000 --- a/src/vs/base/parts/tree/browser/CollapseAll.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/parts/tree/browser/CollapseAll_inverse.svg b/src/vs/base/parts/tree/browser/CollapseAll_inverse.svg deleted file mode 100644 index 46a65fff71a..00000000000 --- a/src/vs/base/parts/tree/browser/CollapseAll_inverse.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/parts/tree/browser/collapse-all-dark.svg b/src/vs/base/parts/tree/browser/collapse-all-dark.svg new file mode 100644 index 00000000000..4862c55dbeb --- /dev/null +++ b/src/vs/base/parts/tree/browser/collapse-all-dark.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/vs/base/parts/tree/browser/collapse-all-hc.svg b/src/vs/base/parts/tree/browser/collapse-all-hc.svg new file mode 100644 index 00000000000..05f920b29b6 --- /dev/null +++ b/src/vs/base/parts/tree/browser/collapse-all-hc.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/vs/base/parts/tree/browser/collapse-all-light.svg b/src/vs/base/parts/tree/browser/collapse-all-light.svg new file mode 100644 index 00000000000..6359b42e623 --- /dev/null +++ b/src/vs/base/parts/tree/browser/collapse-all-light.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/vs/base/parts/tree/browser/collapsed-dark.svg b/src/vs/base/parts/tree/browser/collapsed-dark.svg deleted file mode 100755 index cf5c3641aa7..00000000000 --- a/src/vs/base/parts/tree/browser/collapsed-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/parts/tree/browser/collapsed-hc.svg b/src/vs/base/parts/tree/browser/collapsed-hc.svg deleted file mode 100644 index 145c763338f..00000000000 --- a/src/vs/base/parts/tree/browser/collapsed-hc.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/parts/tree/browser/collapsed.svg b/src/vs/base/parts/tree/browser/collapsed.svg deleted file mode 100755 index 3a63808c358..00000000000 --- a/src/vs/base/parts/tree/browser/collapsed.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/parts/tree/browser/expanded-dark.svg b/src/vs/base/parts/tree/browser/expanded-dark.svg deleted file mode 100755 index 73d41e63990..00000000000 --- a/src/vs/base/parts/tree/browser/expanded-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/parts/tree/browser/expanded-hc.svg b/src/vs/base/parts/tree/browser/expanded-hc.svg deleted file mode 100644 index d38d4abc89e..00000000000 --- a/src/vs/base/parts/tree/browser/expanded-hc.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/parts/tree/browser/tree-collapsed-dark.svg b/src/vs/base/parts/tree/browser/tree-collapsed-dark.svg new file mode 100644 index 00000000000..c2c2298dd5c --- /dev/null +++ b/src/vs/base/parts/tree/browser/tree-collapsed-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/parts/tree/browser/tree-collapsed-hc.svg b/src/vs/base/parts/tree/browser/tree-collapsed-hc.svg new file mode 100644 index 00000000000..3732cbc04b8 --- /dev/null +++ b/src/vs/base/parts/tree/browser/tree-collapsed-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/parts/tree/browser/tree-collapsed-light.svg b/src/vs/base/parts/tree/browser/tree-collapsed-light.svg new file mode 100644 index 00000000000..1952ad63f84 --- /dev/null +++ b/src/vs/base/parts/tree/browser/tree-collapsed-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/parts/tree/browser/tree-expanded-dark.svg b/src/vs/base/parts/tree/browser/tree-expanded-dark.svg new file mode 100644 index 00000000000..d844b383ed3 --- /dev/null +++ b/src/vs/base/parts/tree/browser/tree-expanded-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/parts/tree/browser/tree-expanded-hc.svg b/src/vs/base/parts/tree/browser/tree-expanded-hc.svg new file mode 100644 index 00000000000..9faa2b2a6ed --- /dev/null +++ b/src/vs/base/parts/tree/browser/tree-expanded-hc.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/parts/tree/browser/tree-expanded-light.svg b/src/vs/base/parts/tree/browser/tree-expanded-light.svg new file mode 100644 index 00000000000..f09125caf91 --- /dev/null +++ b/src/vs/base/parts/tree/browser/tree-expanded-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/vs/base/parts/tree/browser/tree.css b/src/vs/base/parts/tree/browser/tree.css index 6e835d22e0c..2a3cb47ddbb 100644 --- a/src/vs/base/parts/tree/browser/tree.css +++ b/src/vs/base/parts/tree/browser/tree.css @@ -66,7 +66,7 @@ content: ' '; position: absolute; display: block; - background: url('collapsed.svg') 50% 50% no-repeat; + background: url('tree-collapsed-light.svg') 50% 50% no-repeat; width: 16px; height: 100%; top: 0; @@ -74,7 +74,7 @@ } .monaco-tree .monaco-tree-rows.show-twisties > .monaco-tree-row.expanded > .content:before { - background-image: url('expanded.svg'); + background-image: url('tree-expanded-light.svg'); } .monaco-tree .monaco-tree-rows > .monaco-tree-row.has-children.loading > .content:before { @@ -88,11 +88,11 @@ } .vs-dark .monaco-tree .monaco-tree-rows.show-twisties > .monaco-tree-row.has-children > .content:before { - background-image: url('collapsed-dark.svg'); + background-image: url('tree-collapsed-dark.svg'); } .vs-dark .monaco-tree .monaco-tree-rows.show-twisties > .monaco-tree-row.expanded > .content:before { - background-image: url('expanded-dark.svg'); + background-image: url('tree-expanded-dark.svg'); } .vs-dark .monaco-tree .monaco-tree-rows > .monaco-tree-row.has-children.loading > .content:before { @@ -100,11 +100,11 @@ } .hc-black .monaco-tree .monaco-tree-rows.show-twisties > .monaco-tree-row.has-children > .content:before { - background-image: url('collapsed-hc.svg'); + background-image: url('tree-collapsed-hc.svg'); } .hc-black .monaco-tree .monaco-tree-rows.show-twisties > .monaco-tree-row.expanded > .content:before { - background-image: url('expanded-hc.svg'); + background-image: url('tree-expanded-hc.svg'); } .hc-black .monaco-tree .monaco-tree-rows > .monaco-tree-row.has-children.loading > .content:before { @@ -112,10 +112,13 @@ } .monaco-tree-action.collapse-all { - background: url('CollapseAll.svg') center center no-repeat; + background: url('collapse-all-light.svg') center center no-repeat; } -.hc-black .monaco-tree-action.collapse-all, .vs-dark .monaco-tree-action.collapse-all { - background: url('CollapseAll_inverse.svg') center center no-repeat; + background: url('collapse-all-dark.svg') center center no-repeat; +} + +.hc-black .monaco-tree-action.collapse-all { + background: url('collapse-all-hc.svg') center center no-repeat; } diff --git a/src/vs/base/parts/tree/browser/tree.ts b/src/vs/base/parts/tree/browser/tree.ts index 9c10466ddf7..82b4015e6dd 100644 --- a/src/vs/base/parts/tree/browser/tree.ts +++ b/src/vs/base/parts/tree/browser/tree.ts @@ -9,9 +9,10 @@ import * as Keyboard from 'vs/base/browser/keyboardEvent'; import { INavigator } from 'vs/base/common/iterator'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { Event } from 'vs/base/common/event'; -import { IAction, IActionItem } from 'vs/base/common/actions'; +import { IAction } from 'vs/base/common/actions'; import { Color } from 'vs/base/common/color'; import { IItemCollapseEvent, IItemExpandEvent } from 'vs/base/parts/tree/browser/treeModel'; +import { IDragAndDropData } from 'vs/base/browser/dnd'; export interface ITree { @@ -77,11 +78,6 @@ export interface ITree { */ refresh(element?: any, recursive?: boolean): Promise; - /** - * Updates an element's width. - */ - updateWidth(element: any): void; - /** * Expands an element. * The returned promise returns a boolean for whether the element was expanded or not. @@ -112,142 +108,37 @@ export interface ITree { */ toggleExpansion(element: any, recursive?: boolean): Promise; - /** - * Toggles several element's expansion state. - */ - toggleExpansionAll(elements: any[]): Promise; - /** * Returns whether an element is expanded or not. */ isExpanded(element: any): boolean; - /** - * Returns a list of the currently expanded elements. - */ - getExpandedElements(): any[]; - /** * Reveals an element in the tree. The relativeTop is a value between 0 and 1. The closer to 0 the more the * element will scroll up to the top. */ reveal(element: any, relativeTop?: number): Promise; - /** - * Returns the relative top position of any given element, if visible. - * If not visible, returns a negative number or a number > 1. - * Useful when calling `reveal(element, relativeTop)`. - */ - getRelativeTop(element: any): number; - - /** - * Returns the top-most visible element. - */ - getFirstVisibleElement(): any; - - /** - * Returns a number between 0 and 1 representing how much the tree is scroll down. 0 means all the way - * to the top; 1 means all the way down. - */ - getScrollPosition(): number; - - /** - * Sets the scroll position with a number between 0 and 1 representing how much the tree is scroll down. 0 means all the way - * to the top; 1 means all the way down. - */ - setScrollPosition(pos: number): void; - - /** - * Returns the total height of the tree's content. - */ - getContentHeight(): number; - - /** - * Sets the tree's highlight to be the given element. - * Provide no arguments and it clears the tree's highlight. - */ - setHighlight(element?: any, eventPayload?: any): void; - /** * Returns the currently highlighted element. */ getHighlight(includeHidden?: boolean): any; - /** - * Returns whether an element is highlighted or not. - */ - isHighlighted(element: any): boolean; - /** * Clears the highlight. */ clearHighlight(eventPayload?: any): void; - /** - * Selects an element. - */ - select(element: any, eventPayload?: any): void; - - /** - * Selects a range of elements. - */ - selectRange(fromElement: any, toElement: any, eventPayload?: any): void; - - /** - * Deselects a range of elements. - */ - deselectRange(fromElement: any, toElement: any, eventPayload?: any): void; - - /** - * Selects several elements. - */ - selectAll(elements: any[], eventPayload?: any): void; - - /** - * Deselects an element. - */ - deselect(element: any, eventPayload?: any): void; - - /** - * Deselects several elements. - */ - deselectAll(elements: any[], eventPayload?: any): void; - /** * Replaces the current selection with the given elements. */ setSelection(elements: any[], eventPayload?: any): void; - /** - * Toggles the element's selection. - */ - toggleSelection(element: any, eventPayload?: any): void; - /** * Returns the currently selected elements. */ getSelection(includeHidden?: boolean): any[]; - /** - * Returns whether an element is selected or not. - */ - isSelected(element: any): boolean; - - /** - * Selects the next `count`-nth element, in visible order. - */ - selectNext(count?: number, clearSelection?: boolean, eventPayload?: any): void; - - /** - * Selects the previous `count`-nth element, in visible order. - */ - selectPrevious(count?: number, clearSelection?: boolean, eventPayload?: any): void; - - /** - * Selects the currently selected element's parent. - */ - selectParent(clearSelection?: boolean, eventPayload?: any): void; - /** * Clears the selection. */ @@ -258,11 +149,6 @@ export interface ITree { */ setFocus(element?: any, eventPayload?: any): void; - /** - * Returns whether an element is focused or not. - */ - isFocused(element: any): boolean; - /** * Returns focused element. */ @@ -320,26 +206,6 @@ export interface ITree { */ clearFocus(eventPayload?: any): void; - /** - * Adds the trait to elements. - */ - addTraits(trait: string, elements: any[]): void; - - /** - * Removes the trait from elements. - */ - removeTraits(trait: string, elements: any[]): void; - - /** - * Toggles the element's trait. - */ - toggleTrait(trait: string, element: any): void; - - /** - * Returns whether the element has the trait or not. - */ - hasTrait(trait: string, element: any): boolean; - /** * Returns a navigator which allows to discover the visible and * expanded elements in the tree. @@ -365,7 +231,7 @@ export interface IDataSource { * * You should not attempt to "move" an element to a different * parent by keeping its ID. The idea here is to have tree location - * related IDs (eg. full file path, in the Explorer example). + * related IDs (e.g. full file path, in the Explorer example). */ getId(tree: ITree, element: any): string; @@ -442,7 +308,7 @@ export interface IAccessibilityProvider { * * See also: https://www.w3.org/TR/wai-aria/states_and_properties#aria-label */ - getAriaLabel(tree: ITree, element: any): string; + getAriaLabel(tree: ITree, element: any): string | null; /** * Given an element in the tree return its aria-posinset. Should be between 1 and aria-setsize @@ -586,25 +452,13 @@ export interface IDragOverReaction { autoExpand?: boolean; } -export const DRAG_OVER_REJECT: IDragOverReaction = { accept: false }; -export const DRAG_OVER_ACCEPT: IDragOverReaction = { accept: true }; -export const DRAG_OVER_ACCEPT_BUBBLE_UP: IDragOverReaction = { accept: true, bubble: DragOverBubble.BUBBLE_UP }; -export const DRAG_OVER_ACCEPT_BUBBLE_DOWN = (autoExpand = false) => ({ accept: true, bubble: DragOverBubble.BUBBLE_DOWN, autoExpand }); -export const DRAG_OVER_ACCEPT_BUBBLE_UP_COPY: IDragOverReaction = { accept: true, bubble: DragOverBubble.BUBBLE_UP, effect: DragOverEffect.COPY }; -export const DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY = (autoExpand = false) => ({ accept: true, bubble: DragOverBubble.BUBBLE_DOWN, effect: DragOverEffect.COPY, autoExpand }); - -export interface IDragAndDropData { - update(event: Mouse.DragMouseEvent): void; - getData(): any; -} - export interface IDragAndDrop { /** * Returns a uri if the given element should be allowed to drag. * Returns null, otherwise. */ - getDragURI(tree: ITree, element: any): string; + getDragURI(tree: ITree, element: any): string | null; /** * Returns a label to display when dragging the element. @@ -620,7 +474,7 @@ export interface IDragAndDrop { * Returns a DragOverReaction indicating whether sources can be * dropped into target or some parent of the target. */ - onDragOver(tree: ITree, data: IDragAndDropData, targetElement: any, originalEvent: Mouse.DragMouseEvent): IDragOverReaction; + onDragOver(tree: ITree, data: IDragAndDropData, targetElement: any, originalEvent: Mouse.DragMouseEvent): IDragOverReaction | null; /** * Handles the action of dropping sources into target. @@ -636,12 +490,6 @@ export interface IFilter { isVisible(tree: ITree, element: any): boolean; } -export interface IElementCallback { - (tree: ITree, element: any): void; -} - -export type ICallback = () => void; - export interface ISorter { /** @@ -725,25 +573,10 @@ export interface IActionProvider { /** * Returns whether or not the element has actions. These show up in place right to the element in the tree. */ - hasActions(tree: ITree, element: any): boolean; + hasActions(tree: ITree | null, element: any): boolean; /** - * Returns a promise of an array with the actions of the element that should show up in place right to the element in the tree. + * Returns an array with the actions of the element that should show up in place right to the element in the tree. */ - getActions(tree: ITree, element: any): IAction[]; - - /** - * Returns whether or not the element has secondary actions. These show up once the user has expanded the element's action bar. - */ - hasSecondaryActions(tree: ITree, element: any): boolean; - - /** - * Returns a promise of an array with the secondary actions of the element that should show up once the user has expanded the element's action bar. - */ - getSecondaryActions(tree: ITree, element: any): IAction[]; - - /** - * Returns an action item to render an action. - */ - getActionItem(tree: ITree, element: any, action: IAction): IActionItem; + getActions(tree: ITree | null, element: any): ReadonlyArray | null; } diff --git a/src/vs/base/parts/tree/browser/treeDefaults.ts b/src/vs/base/parts/tree/browser/treeDefaults.ts index 89122b80d2f..f91ca2bcf84 100644 --- a/src/vs/base/parts/tree/browser/treeDefaults.ts +++ b/src/vs/base/parts/tree/browser/treeDefaults.ts @@ -12,7 +12,8 @@ import * as dom from 'vs/base/browser/dom'; import * as mouse from 'vs/base/browser/mouseEvent'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import * as _ from 'vs/base/parts/tree/browser/tree'; -import { KeyCode, KeyMod, Keybinding, createKeybinding, SimpleKeybinding, createSimpleKeybinding } from 'vs/base/common/keyCodes'; +import { IDragAndDropData } from 'vs/base/browser/dnd'; +import { KeyCode, KeyMod, Keybinding, SimpleKeybinding, createKeybinding } from 'vs/base/common/keyCodes'; export interface IKeyBindingCallback { (tree: _.ITree, event: IKeyboardEvent): void; @@ -48,7 +49,7 @@ export interface IControllerOptions { } interface IKeybindingDispatcherItem { - keybinding: Keybinding; + keybinding: Keybinding | null; callback: IKeyBindingCallback; } @@ -61,27 +62,29 @@ export class KeybindingDispatcher { } public has(keybinding: KeyCode): boolean { - let target = createSimpleKeybinding(keybinding, platform.OS); - for (const a of this._arr) { - if (target.equals(a.keybinding)) { - return true; + let target = createKeybinding(keybinding, platform.OS); + if (target !== null) { + for (const a of this._arr) { + if (target.equals(a.keybinding)) { + return true; + } } } return false; } - public set(keybinding: KeyCode, callback: IKeyBindingCallback) { + public set(keybinding: number, callback: IKeyBindingCallback) { this._arr.push({ keybinding: createKeybinding(keybinding, platform.OS), callback: callback }); } - public dispatch(keybinding: SimpleKeybinding): IKeyBindingCallback { + public dispatch(keybinding: SimpleKeybinding): IKeyBindingCallback | null { // Loop from the last to the first to handle overwrites for (let i = this._arr.length - 1; i >= 0; i--) { let item = this._arr[i]; - if (keybinding.equals(item.keybinding)) { + if (keybinding.toChord().equals(item.keybinding)) { return item.callback; } } @@ -225,7 +228,7 @@ export class DefaultController implements _.IController { return false; } - const twistieWidth = parseInt(twistieStyle.width) + parseInt(twistieStyle.paddingRight); + const twistieWidth = parseInt(twistieStyle.width!) + parseInt(twistieStyle.paddingRight!); return event.browserEvent.offsetX <= twistieWidth; } @@ -430,19 +433,19 @@ export class DefaultController implements _.IController { export class DefaultDragAndDrop implements _.IDragAndDrop { - public getDragURI(tree: _.ITree, element: any): string { + public getDragURI(tree: _.ITree, element: any): string | null { return null; } - public onDragStart(tree: _.ITree, data: _.IDragAndDropData, originalEvent: mouse.DragMouseEvent): void { + public onDragStart(tree: _.ITree, data: IDragAndDropData, originalEvent: mouse.DragMouseEvent): void { return; } - public onDragOver(tree: _.ITree, data: _.IDragAndDropData, targetElement: any, originalEvent: mouse.DragMouseEvent): _.IDragOverReaction { + public onDragOver(tree: _.ITree, data: IDragAndDropData, targetElement: any, originalEvent: mouse.DragMouseEvent): _.IDragOverReaction | null { return null; } - public drop(tree: _.ITree, data: _.IDragAndDropData, targetElement: any, originalEvent: mouse.DragMouseEvent): void { + public drop(tree: _.ITree, data: IDragAndDropData, targetElement: any, originalEvent: mouse.DragMouseEvent): void { return; } } @@ -463,7 +466,7 @@ export class DefaultSorter implements _.ISorter { export class DefaultAccessibilityProvider implements _.IAccessibilityProvider { - getAriaLabel(tree: _.ITree, element: any): string { + getAriaLabel(tree: _.ITree, element: any): string | null { return null; } } @@ -552,7 +555,7 @@ export class DefaultTreestyler implements _.ITreeStyler { export class CollapseAllAction extends Action { constructor(private viewer: _.ITree, enabled: boolean) { - super('vs.tree.collapse', nls.localize('collapse', "Collapse"), 'monaco-tree-action collapse-all', enabled); + super('vs.tree.collapse', nls.localize('collapse all', "Collapse All"), 'monaco-tree-action collapse-all', enabled); } public run(context?: any): Promise { diff --git a/src/vs/base/parts/tree/browser/treeDnd.ts b/src/vs/base/parts/tree/browser/treeDnd.ts index 5ba6467296b..810e6ce98ee 100644 --- a/src/vs/base/parts/tree/browser/treeDnd.ts +++ b/src/vs/base/parts/tree/browser/treeDnd.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import * as _ from 'vs/base/parts/tree/browser/tree'; -import * as Mouse from 'vs/base/browser/mouseEvent'; +import { IDragAndDropData } from 'vs/base/browser/dnd'; -export class ElementsDragAndDropData implements _.IDragAndDropData { +export class ElementsDragAndDropData implements IDragAndDropData { private elements: any[]; @@ -14,7 +14,7 @@ export class ElementsDragAndDropData implements _.IDragAndDropData { this.elements = elements; } - public update(event: Mouse.DragMouseEvent): void { + public update(dataTransfer: DataTransfer): void { // no-op } @@ -23,7 +23,7 @@ export class ElementsDragAndDropData implements _.IDragAndDropData { } } -export class ExternalElementsDragAndDropData implements _.IDragAndDropData { +export class ExternalElementsDragAndDropData implements IDragAndDropData { private elements: any[]; @@ -31,7 +31,7 @@ export class ExternalElementsDragAndDropData implements _.IDragAndDropData { this.elements = elements; } - public update(event: Mouse.DragMouseEvent): void { + public update(dataTransfer: DataTransfer): void { // no-op } @@ -40,7 +40,7 @@ export class ExternalElementsDragAndDropData implements _.IDragAndDropData { } } -export class DesktopDragAndDropData implements _.IDragAndDropData { +export class DesktopDragAndDropData implements IDragAndDropData { private types: any[]; private files: any[]; @@ -50,15 +50,15 @@ export class DesktopDragAndDropData implements _.IDragAndDropData { this.files = []; } - public update(event: Mouse.DragMouseEvent): void { - if (event.dataTransfer.types) { + public update(dataTransfer: DataTransfer): void { + if (dataTransfer.types) { this.types = []; - Array.prototype.push.apply(this.types, event.dataTransfer.types); + Array.prototype.push.apply(this.types, dataTransfer.types as any); } - if (event.dataTransfer.files) { + if (dataTransfer.files) { this.files = []; - Array.prototype.push.apply(this.files, event.dataTransfer.files); + Array.prototype.push.apply(this.files, dataTransfer.files as any); this.files = this.files.filter(f => f.size || f.type); } diff --git a/src/vs/base/parts/tree/browser/treeImpl.ts b/src/vs/base/parts/tree/browser/treeImpl.ts index 1bd18fb65ff..3f30ea46037 100644 --- a/src/vs/base/parts/tree/browser/treeImpl.ts +++ b/src/vs/base/parts/tree/browser/treeImpl.ts @@ -20,13 +20,13 @@ export class TreeContext implements _.ITreeContext { public options: _.ITreeOptions; public dataSource: _.IDataSource; - public renderer: _.IRenderer; + public renderer?: _.IRenderer; public controller: _.IController; public dnd: _.IDragAndDrop; public filter: _.IFilter; - public sorter: _.ISorter; + public sorter?: _.ISorter; public accessibilityProvider: _.IAccessibilityProvider; - public styler: _.ITreeStyler; + public styler?: _.ITreeStyler; constructor(tree: _.ITree, configuration: _.ITreeConfiguration, options: _.ITreeOptions = {}) { this.tree = tree; @@ -42,9 +42,9 @@ export class TreeContext implements _.ITreeContext { this.controller = configuration.controller || new TreeDefaults.DefaultController({ clickBehavior: TreeDefaults.ClickBehavior.ON_MOUSE_UP, keyboardSupport: typeof options.keyboardSupport !== 'boolean' || options.keyboardSupport }); this.dnd = configuration.dnd || new TreeDefaults.DefaultDragAndDrop(); this.filter = configuration.filter || new TreeDefaults.DefaultFilter(); - this.sorter = configuration.sorter || null; + this.sorter = configuration.sorter; this.accessibilityProvider = configuration.accessibilityProvider || new TreeDefaults.DefaultAccessibilityProvider(); - this.styler = configuration.styler || null; + this.styler = configuration.styler; } } @@ -161,11 +161,6 @@ export class Tree implements _.ITree { return this.model.refresh(element, recursive); } - public updateWidth(element: any): void { - let item = this.model.getItem(element); - return this.view.updateWidth(item); - } - public expand(element: any): Promise { return this.model.expand(element); } @@ -186,99 +181,26 @@ export class Tree implements _.ITree { return this.model.toggleExpansion(element, recursive); } - public toggleExpansionAll(elements: any[]): Promise { - return this.model.toggleExpansionAll(elements); - } - public isExpanded(element: any): boolean { return this.model.isExpanded(element); } - public getExpandedElements(): any[] { - return this.model.getExpandedElements(); - } - public reveal(element: any, relativeTop: number | null = null): Promise { return this.model.reveal(element, relativeTop); } - public getRelativeTop(element: any): number { - let item = this.model.getItem(element); - return this.view.getRelativeTop(item); - } - - public getFirstVisibleElement(): any { - return this.view.getFirstVisibleElement(); - } - - public getLastVisibleElement(): any { - return this.view.getLastVisibleElement(); - } - - public getScrollPosition(): number { - return this.view.getScrollPosition(); - } - - public setScrollPosition(pos: number): void { - this.view.setScrollPosition(pos); - } - - getContentHeight(): number { - return this.view.getContentHeight(); - } - - public setHighlight(element?: any, eventPayload?: any): void { - this.model.setHighlight(element, eventPayload); - } - public getHighlight(): any { return this.model.getHighlight(); } - public isHighlighted(element: any): boolean { - return this.model.isFocused(element); - } - public clearHighlight(eventPayload?: any): void { this.model.setHighlight(null, eventPayload); } - public select(element: any, eventPayload?: any): void { - this.model.select(element, eventPayload); - } - - public selectRange(fromElement: any, toElement: any, eventPayload?: any): void { - this.model.selectRange(fromElement, toElement, eventPayload); - } - - public deselectRange(fromElement: any, toElement: any, eventPayload?: any): void { - this.model.deselectRange(fromElement, toElement, eventPayload); - } - - public selectAll(elements: any[], eventPayload?: any): void { - this.model.selectAll(elements, eventPayload); - } - - public deselect(element: any, eventPayload?: any): void { - this.model.deselect(element, eventPayload); - } - - public deselectAll(elements: any[], eventPayload?: any): void { - this.model.deselectAll(elements, eventPayload); - } - public setSelection(elements: any[], eventPayload?: any): void { this.model.setSelection(elements, eventPayload); } - public toggleSelection(element: any, eventPayload?: any): void { - this.model.toggleSelection(element, eventPayload); - } - - public isSelected(element: any): boolean { - return this.model.isSelected(element); - } - public getSelection(): any[] { return this.model.getSelection(); } @@ -287,26 +209,10 @@ export class Tree implements _.ITree { this.model.setSelection([], eventPayload); } - public selectNext(count?: number, clearSelection?: boolean, eventPayload?: any): void { - this.model.selectNext(count, clearSelection, eventPayload); - } - - public selectPrevious(count?: number, clearSelection?: boolean, eventPayload?: any): void { - this.model.selectPrevious(count, clearSelection, eventPayload); - } - - public selectParent(clearSelection?: boolean, eventPayload?: any): void { - this.model.selectParent(clearSelection, eventPayload); - } - public setFocus(element?: any, eventPayload?: any): void { this.model.setFocus(element, eventPayload); } - public isFocused(element: any): boolean { - return this.model.isFocused(element); - } - public getFocus(): any { return this.model.getFocus(); } @@ -351,23 +257,6 @@ export class Tree implements _.ITree { this.model.setFocus(null, eventPayload); } - public addTraits(trait: string, elements: any[]): void { - this.model.addTraits(trait, elements); - } - - public removeTraits(trait: string, elements: any[]): void { - this.model.removeTraits(trait, elements); - } - - public toggleTrait(trait: string, element: any): void { - this.model.hasTrait(trait, element) ? this.model.removeTraits(trait, [element]) - : this.model.addTraits(trait, [element]); - } - - public hasTrait(trait: string, element: any): boolean { - return this.model.hasTrait(trait, element); - } - getNavigator(fromElement?: any, subTreeOnly?: boolean): INavigator { return new MappedNavigator(this.model.getNavigator(fromElement, subTreeOnly), i => i && i.getElement()); } @@ -377,11 +266,11 @@ export class Tree implements _.ITree { if (this.model !== null) { this.model.dispose(); - this.model = null; + this.model = null!; // StrictNullOverride Nulling out ok in dispose } if (this.view !== null) { this.view.dispose(); - this.view = null; + this.view = null!; // StrictNullOverride Nulling out ok in dispose } this._onDidChangeFocus.dispose(); diff --git a/src/vs/base/parts/tree/browser/treeModel.ts b/src/vs/base/parts/tree/browser/treeModel.ts index f134acde692..6f157d62e05 100644 --- a/src/vs/base/parts/tree/browser/treeModel.ts +++ b/src/vs/base/parts/tree/browser/treeModel.ts @@ -6,7 +6,6 @@ import * as Assert from 'vs/base/common/assert'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; -import * as arrays from 'vs/base/common/arrays'; import { INavigator } from 'vs/base/common/iterator'; import * as _ from './tree'; import { Event, Emitter, EventMultiplexer, Relay } from 'vs/base/common/event'; @@ -18,8 +17,8 @@ interface ITraitMap extends IMap { } export class LockData { private _item: Item; - private _onDispose = new Emitter(); - readonly onDispose: Event = this._onDispose.event; + private _onDispose?= new Emitter(); + readonly onDispose: Event = this._onDispose!.event; constructor(item: Item) { this._item = item; @@ -33,7 +32,7 @@ export class LockData { if (this._onDispose) { this._onDispose.fire(); this._onDispose.dispose(); - this._onDispose = null; + this._onDispose = undefined; } } } @@ -79,7 +78,7 @@ export class Lock { } public run(item: Item, fn: () => Promise): Promise { - let lock = this.getLock(item); + const lock = this.getLock(item); if (lock) { return new Promise((c, e) => { @@ -110,7 +109,7 @@ export class Lock { }); } - private getLock(item: Item): LockData { + private getLock(item: Item): LockData | null { let key: string; for (key in this.locks) { @@ -160,7 +159,7 @@ export class ItemRegistry { public register(item: Item): void { Assert.ok(!this.isRegistered(item.id), 'item already registered: ' + item.id); - const disposable = combinedDisposable([ + const disposable = combinedDisposable( this._onDidRevealItem.add(item.onDidReveal), this._onExpandItem.add(item.onExpand), this._onDidExpandItem.add(item.onDidExpand), @@ -172,7 +171,7 @@ export class ItemRegistry { this._onRefreshItemChildren.add(item.onRefreshChildren), this._onDidRefreshItemChildren.add(item.onDidRefreshChildren), this._onDidDisposeItem.add(item.onDidDispose) - ]); + ); this.items[item.id] = { item, disposable }; } @@ -187,13 +186,13 @@ export class ItemRegistry { return this.items.hasOwnProperty(id); } - public getItem(id: string): Item { + public getItem(id: string): Item | null { const result = this.items[id]; return result ? result.item : null; } public dispose(): void { - this.items = null; + this.items = null!; // StrictNullOverride: nulling out ok in dispose this._onDidRevealItem.dispose(); this._onExpandItem.dispose(); @@ -227,7 +226,7 @@ export interface IItemTraitEvent extends IBaseItemEvent { } export interface IItemRevealEvent extends IBaseItemEvent { - relativeTop: number; + relativeTop: number | null; } export interface IItemChildrenRefreshEvent extends IBaseItemEvent { @@ -246,11 +245,11 @@ export class Item { private needsChildrenRefresh: boolean; private doesHaveChildren: boolean; - public parent: Item; - public previous: Item; - public next: Item; - public firstChild: Item; - public lastChild: Item; + public parent: Item | null; + public previous: Item | null; + public next: Item | null; + public firstChild: Item | null; + public lastChild: Item | null; private height: number; private depth: number; @@ -307,7 +306,7 @@ export class Item { this.traits = {}; this.depth = 0; - this.expanded = this.context.dataSource.shouldAutoexpand && this.context.dataSource.shouldAutoexpand(this.context.tree, element); + this.expanded = !!(this.context.dataSource.shouldAutoexpand && this.context.dataSource.shouldAutoexpand(this.context.tree, element)); this._onDidCreate.fire(this); @@ -558,20 +557,8 @@ export class Item { return this.isAncestorOf(other) || other.isAncestorOf(this); } - public getHierarchy(): Item[] { - let result: Item[] = []; - let node: Item = this; - - do { - result.push(node); - node = node.parent; - } while (node); - - result.reverse(); - return result; - } - - private isAncestorOf(item: Item): boolean { + private isAncestorOf(startItem: Item): boolean { + let item: Item | null = startItem; while (item) { if (item.id === this.id) { return true; @@ -581,7 +568,7 @@ export class Item { return false; } - private addChild(item: Item, afterItem: Item = this.lastChild): void { + private addChild(item: Item, afterItem: Item | null = this.lastChild): void { let isEmpty = this.firstChild === null; let atHead = afterItem === null; let atTail = afterItem === this.lastChild; @@ -590,18 +577,30 @@ export class Item { this.firstChild = this.lastChild = item; item.next = item.previous = null; } else if (atHead) { + if (!this.firstChild) { + throw new Error('Invalid tree state'); + } this.firstChild.previous = item; item.next = this.firstChild; item.previous = null; this.firstChild = item; } else if (atTail) { + if (!this.lastChild) { + throw new Error('Invalid tree state'); + } this.lastChild.next = item; item.next = null; item.previous = this.lastChild; this.lastChild = item; } else { item.previous = afterItem; + if (!afterItem) { + throw new Error('Invalid tree state'); + } item.next = afterItem.next; + if (!afterItem.next) { + throw new Error('Invalid tree state'); + } afterItem.next.previous = item; afterItem.next = item; } @@ -617,22 +616,35 @@ export class Item { if (isFirstChild && isLastChild) { this.firstChild = this.lastChild = null; } else if (isFirstChild) { + if (!item.next) { + throw new Error('Invalid tree state'); + } item.next.previous = null; this.firstChild = item.next; } else if (isLastChild) { + if (!item.previous) { + throw new Error('Invalid tree state'); + } item.previous.next = null; this.lastChild = item.previous; } else { + if (!item.next) { + throw new Error('Invalid tree state'); + } item.next.previous = item.previous; + if (!item.previous) { + throw new Error('Invalid tree state'); + } item.previous.next = item.next; } item.parent = null; - item.depth = null; + item.depth = NaN; } private forEachChild(fn: (child: Item) => void): void { - let child = this.firstChild, next: Item; + let child = this.firstChild; + let next: Item | null; while (child) { next = child.next; fn(child); @@ -649,9 +661,10 @@ export class Item { } private sort(elements: any[]): any[] { - if (this.context.sorter) { + const sorter = this.context.sorter; + if (sorter) { return elements.sort((element, otherElement) => { - return this.context.sorter.compare(this.context.tree, element, otherElement); + return sorter.compare(this.context.tree, element, otherElement); }); } @@ -659,10 +672,16 @@ export class Item { } /* protected */ public _getHeight(): number { + if (!this.context.renderer) { + return 0; + } return this.context.renderer.getHeight(this.context.tree, this.element); } /* protected */ public _isVisible(): boolean { + if (!this.context.filter) { + return false; + } return this.context.filter.isVisible(this.context.tree, this.element); } @@ -737,10 +756,10 @@ class RootItem extends Item { export class TreeNavigator implements INavigator { - private start: Item; - private item: Item; + private start: Item | null; + private item: Item | null; - static lastDescendantOf(item: Item): Item { + static lastDescendantOf(item: Item | null): Item | null { if (!item) { return null; } @@ -760,16 +779,16 @@ export class TreeNavigator implements INavigator { return TreeNavigator.lastDescendantOf(item.lastChild); } - constructor(item: Item, subTreeOnly: boolean = true) { + constructor(item: Item | null, subTreeOnly: boolean = true) { this.item = item; this.start = subTreeOnly ? item : null; } - public current(): Item { + public current(): Item | null { return this.item || null; } - public next(): Item { + public next(): Item | null { if (this.item) { do { if ((this.item instanceof RootItem || (this.item.isVisible() && this.item.isExpanded())) && this.item.firstChild) { @@ -791,7 +810,7 @@ export class TreeNavigator implements INavigator { return this.item || null; } - public previous(): Item { + public previous(): Item | null { if (this.item) { do { let previous = TreeNavigator.lastDescendantOf(this.item.previous); @@ -807,7 +826,7 @@ export class TreeNavigator implements INavigator { return this.item || null; } - public parent(): Item { + public parent(): Item | null { if (this.item) { let parent = this.item.parent; if (parent && parent !== this.start && parent.isVisible()) { @@ -819,55 +838,19 @@ export class TreeNavigator implements INavigator { return this.item || null; } - public first(): Item { + public first(): Item | null { this.item = this.start; this.next(); return this.item || null; } - public last(): Item { + public last(): Item | null { return TreeNavigator.lastDescendantOf(this.start); } } -function getRange(one: Item, other: Item): Item[] { - let oneHierarchy = one.getHierarchy(); - let otherHierarchy = other.getHierarchy(); - let length = arrays.commonPrefixLength(oneHierarchy, otherHierarchy); - let item = oneHierarchy[length - 1]; - let nav = item.getNavigator(); - - let oneIndex: number | null = null; - let otherIndex: number | null = null; - - let index = 0; - let result: Item[] = []; - - while (item && (oneIndex === null || otherIndex === null)) { - result.push(item); - - if (item === one) { - oneIndex = index; - } - if (item === other) { - otherIndex = index; - } - - index++; - item = nav.next(); - } - - if (oneIndex === null || otherIndex === null) { - return []; - } - - let min = Math.min(oneIndex, otherIndex); - let max = Math.max(oneIndex, otherIndex); - return result.slice(min, max + 1); -} - export interface IBaseEvent { - item: Item; + item: Item | null; } export interface IInputEvent extends IBaseEvent { } @@ -879,10 +862,10 @@ export interface IRefreshEvent extends IBaseEvent { export class TreeModel { private context: _.ITreeContext; - private lock: Lock; - private input: Item; - private registry: ItemRegistry; - private registryDisposable: IDisposable; + private lock!: Lock; + private input: Item | null; + private registry!: ItemRegistry; + private registryDisposable!: IDisposable; private traitsToItems: ITraitMap; private _onSetInput = new Emitter(); @@ -1004,7 +987,7 @@ export class TreeModel { if (!elements) { elements = []; - let item: Item; + let item: Item | null; let nav = this.getNavigator(); while (item = nav.next()) { @@ -1042,7 +1025,7 @@ export class TreeModel { } private __expandAll(elements: any[]): Promise { - let promises = []; + const promises: Array> = []; for (let i = 0, len = elements.length; i < len; i++) { promises.push(this.expand(elements[i])); } @@ -1050,7 +1033,7 @@ export class TreeModel { } public collapse(element: any, recursive: boolean = false): Promise { - let item = this.getItem(element); + const item = this.getItem(element); if (!item) { return Promise.resolve(false); @@ -1064,7 +1047,7 @@ export class TreeModel { elements = [this.input]; recursive = true; } - let promises = []; + let promises: Array> = []; for (let i = 0, len = elements.length; i < len; i++) { promises.push(this.collapse(elements[i], recursive)); } @@ -1076,7 +1059,7 @@ export class TreeModel { } public toggleExpansionAll(elements: any[]): Promise { - let promises = []; + let promises: Array> = []; for (let i = 0, len = elements.length; i < len; i++) { promises.push(this.toggleExpansion(elements[i])); } @@ -1095,7 +1078,7 @@ export class TreeModel { public getExpandedElements(): any[] { let result: any[] = []; - let item: Item; + let item: Item | null; let nav = this.getNavigator(); while (item = nav.next()) { @@ -1144,7 +1127,7 @@ export class TreeModel { this._onDidHighlight.fire(eventData); } - public getHighlight(includeHidden?: boolean): any { + public getHighlight(includeHidden: boolean = false): any { let result = this.getElementsWithTrait('highlighted', includeHidden); return result.length === 0 ? null : result[0]; } @@ -1163,28 +1146,6 @@ export class TreeModel { this.selectAll([element], eventPayload); } - public selectRange(fromElement: any, toElement: any, eventPayload?: any): void { - let fromItem = this.getItem(fromElement); - let toItem = this.getItem(toElement); - - if (!fromItem || !toItem) { - return; - } - - this.selectAll(getRange(fromItem, toItem), eventPayload); - } - - public deselectRange(fromElement: any, toElement: any, eventPayload?: any): void { - let fromItem = this.getItem(fromElement); - let toItem = this.getItem(toElement); - - if (!fromItem || !toItem) { - return; - } - - this.deselectAll(getRange(fromItem, toItem), eventPayload); - } - public selectAll(elements: any[], eventPayload?: any): void { this.addTraits('selected', elements); let eventData: _.ISelectionEvent = { selection: this.getSelection(), payload: eventPayload }; @@ -1207,12 +1168,6 @@ export class TreeModel { this._onDidSelect.fire(eventData); } - public toggleSelection(element: any, eventPayload?: any): void { - this.toggleTrait('selected', element); - let eventData: _.ISelectionEvent = { selection: this.getSelection(), payload: eventPayload }; - this._onDidSelect.fire(eventData); - } - public isSelected(element: any): boolean { let item = this.getItem(element); @@ -1223,14 +1178,14 @@ export class TreeModel { return item.hasTrait('selected'); } - public getSelection(includeHidden?: boolean): any[] { + public getSelection(includeHidden: boolean = false): any[] { return this.getElementsWithTrait('selected', includeHidden); } public selectNext(count: number = 1, clearSelection: boolean = true, eventPayload?: any): void { let selection = this.getSelection(); let item: Item = selection.length > 0 ? selection[0] : this.input; - let nextItem: Item; + let nextItem: Item | null; let nav = this.getNavigator(item, false); for (let i = 0; i < count; i++) { @@ -1282,21 +1237,6 @@ export class TreeModel { } } - public selectParent(eventPayload?: any, clearSelection: boolean = true): void { - let selection = this.getSelection(); - let item: Item = selection.length > 0 ? selection[0] : this.input; - let nav = this.getNavigator(item, false); - let parent = nav.parent(); - - if (parent) { - if (clearSelection) { - this.setSelection([parent], eventPayload); - } else { - this.select(parent, eventPayload); - } - } - } - public setFocus(element?: any, eventPayload?: any): void { this.setTraits('focused', element ? [element] : []); let eventData: _.IFocusEvent = { focus: this.getFocus(), payload: eventPayload }; @@ -1313,14 +1253,14 @@ export class TreeModel { return item.hasTrait('focused'); } - public getFocus(includeHidden?: boolean): any { + public getFocus(includeHidden: boolean = false): any { let result = this.getElementsWithTrait('focused', includeHidden); return result.length === 0 ? null : result[0]; } public focusNext(count: number = 1, eventPayload?: any): void { let item: Item = this.getFocus() || this.input; - let nextItem: Item; + let nextItem: Item | null; let nav = this.getNavigator(item, false); for (let i = 0; i < count; i++) { @@ -1336,7 +1276,7 @@ export class TreeModel { public focusPrevious(count: number = 1, eventPayload?: any): void { let item: Item = this.getFocus() || this.input; - let previousItem: Item; + let previousItem: Item | null; let nav = this.getNavigator(item, false); for (let i = 0; i < count; i++) { @@ -1389,12 +1329,12 @@ export class TreeModel { } public focusLast(eventPayload?: any, from?: any): void { - let navItem = this.getParent(from); - let item: Item; - if (from) { + const navItem = this.getParent(from); + let item: Item | null; + if (from && navItem) { item = navItem.lastChild; } else { - let nav = this.getNavigator(navItem); + const nav = this.getNavigator(navItem); item = nav.last(); } @@ -1403,9 +1343,9 @@ export class TreeModel { } } - private getParent(from?: any): Item { + private getParent(from?: any): Item | null { if (from) { - let fromItem = this.getItem(from); + const fromItem = this.getItem(from); if (fromItem && fromItem.parent) { return fromItem.parent; } @@ -1418,7 +1358,7 @@ export class TreeModel { return new TreeNavigator(this.getItem(element), subTreeOnly); } - public getItem(element: any = null): Item { + public getItem(element: any = null): Item | null { if (element === null) { return this.input; } else if (element instanceof Item) { @@ -1432,7 +1372,7 @@ export class TreeModel { public addTraits(trait: string, elements: any[]): void { let items: IItemMap = this.traitsToItems[trait] || {}; - let item: Item; + let item: Item | null; for (let i = 0, len = elements.length; i < len; i++) { item = this.getItem(elements[i]); @@ -1446,7 +1386,7 @@ export class TreeModel { public removeTraits(trait: string, elements: any[]): void { let items: IItemMap = this.traitsToItems[trait] || {}; - let item: Item; + let item: Item | null; let id: string; if (elements.length === 0) { @@ -1471,31 +1411,12 @@ export class TreeModel { } } - public hasTrait(trait: string, element: any): boolean { - let item = this.getItem(element); - return item && item.hasTrait(trait); - } - - private toggleTrait(trait: string, element: any): void { - let item = this.getItem(element); - - if (!item) { - return; - } - - if (item.hasTrait(trait)) { - this.removeTraits(trait, [element]); - } else { - this.addTraits(trait, [element]); - } - } - private setTraits(trait: string, elements: any[]): void { if (elements.length === 0) { this.removeTraits(trait, elements); } else { let items: { [id: string]: Item; } = {}; - let item: Item; + let item: Item | null; for (let i = 0, len = elements.length; i < len; i++) { item = this.getItem(elements[i]); @@ -1538,7 +1459,7 @@ export class TreeModel { } private getElementsWithTrait(trait: string, includeHidden: boolean): any[] { - let elements = []; + let elements: any[] = []; let items = this.traitsToItems[trait] || {}; let id: string; for (id in items) { @@ -1552,7 +1473,7 @@ export class TreeModel { public dispose(): void { if (this.registry) { this.registry.dispose(); - this.registry = null; + this.registry = null!; // StrictNullOverride: nulling out ok in dispose } this._onSetInput.dispose(); diff --git a/src/vs/base/parts/tree/browser/treeUtils.ts b/src/vs/base/parts/tree/browser/treeUtils.ts index 00f2ef0f37c..6d536a7fa5a 100644 --- a/src/vs/base/parts/tree/browser/treeUtils.ts +++ b/src/vs/base/parts/tree/browser/treeUtils.ts @@ -5,16 +5,6 @@ import * as _ from 'vs/base/parts/tree/browser/tree'; -export function collapseAll(tree: _.ITree, except?: any): void { - const nav = tree.getNavigator(); - let cur; - while (cur = nav.next()) { - if (!except || !isEqualOrParent(tree, except, cur)) { - tree.collapse(cur); - } - } -} - export function isEqualOrParent(tree: _.ITree, element: any, candidateParent: any): boolean { const nav = tree.getNavigator(element); @@ -26,11 +16,3 @@ export function isEqualOrParent(tree: _.ITree, element: any, candidateParent: an return false; } - -export function expandAll(tree: _.ITree): void { - const nav = tree.getNavigator(); - let cur; - while (cur = nav.next()) { - tree.expand(cur); - } -} diff --git a/src/vs/base/parts/tree/browser/treeView.ts b/src/vs/base/parts/tree/browser/treeView.ts index 144344684ea..71f583acc26 100644 --- a/src/vs/base/parts/tree/browser/treeView.ts +++ b/src/vs/base/parts/tree/browser/treeView.ts @@ -21,19 +21,19 @@ import { HeightMap, IViewItem } from 'vs/base/parts/tree/browser/treeViewModel'; import * as _ from 'vs/base/parts/tree/browser/tree'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Event, Emitter } from 'vs/base/common/event'; -import { DataTransfers } from 'vs/base/browser/dnd'; +import { DataTransfers, StaticDND, IDragAndDropData } from 'vs/base/browser/dnd'; import { DefaultTreestyler } from './treeDefaults'; import { Delayer, timeout } from 'vs/base/common/async'; export interface IRow { - element: HTMLElement; + element: HTMLElement | null; templateId: string; templateData: any; } function removeFromParent(element: HTMLElement): void { try { - element.parentElement.removeChild(element); + element.parentElement!.removeChild(element); } catch (e) { // this will throw if this happens due to a blur event, nasty business } @@ -41,7 +41,7 @@ function removeFromParent(element: HTMLElement): void { export class RowCache implements Lifecycle.IDisposable { - private _cache: { [templateId: string]: IRow[]; }; + private _cache: { [templateId: string]: IRow[]; } | null; constructor(private context: _.ITreeContext) { this._cache = { '': [] }; @@ -60,7 +60,7 @@ export class RowCache implements Lifecycle.IDisposable { let templateData: any = null; try { - templateData = this.context.renderer.renderTemplate(this.context.tree, templateId, content); + templateData = this.context.renderer!.renderTemplate(this.context.tree, templateId, content); } catch (err) { console.error('Tree usage error: exception while rendering template'); console.error(err); @@ -77,24 +77,24 @@ export class RowCache implements Lifecycle.IDisposable { } public release(templateId: string, row: IRow): void { - removeFromParent(row.element); + removeFromParent(row.element!); this.cache(templateId).push(row); } private cache(templateId: string): IRow[] { - return this._cache[templateId] || (this._cache[templateId] = []); + return this._cache![templateId] || (this._cache![templateId] = []); } public garbageCollect(): void { if (this._cache) { Object.keys(this._cache).forEach(templateId => { - this._cache[templateId].forEach(cachedRow => { - this.context.renderer.disposeTemplate(this.context.tree, templateId, cachedRow.templateData); + this._cache![templateId].forEach(cachedRow => { + this.context.renderer!.disposeTemplate(this.context.tree, templateId, cachedRow.templateData); cachedRow.element = null; cachedRow.templateData = null; }); - delete this._cache[templateId]; + delete this._cache![templateId]; }); } } @@ -102,7 +102,6 @@ export class RowCache implements Lifecycle.IDisposable { public dispose(): void { this.garbageCollect(); this._cache = null; - this.context = null; } } @@ -117,20 +116,20 @@ export class ViewItem implements IViewItem { public model: Model.Item; public id: string; - protected row: IRow; + protected row: IRow | null; public top: number; public height: number; public width: number = 0; - public onDragStart: (e: DragEvent) => void; + public onDragStart!: (e: DragEvent) => void; - public needsRender: boolean; - public uri: string; - public unbindDragStart: Lifecycle.IDisposable; + public needsRender: boolean = false; + public uri: string | null = null; + public unbindDragStart: Lifecycle.IDisposable = Lifecycle.Disposable.None; public loadingTimer: any; public _styles: any; - private _draggable: boolean; + private _draggable: boolean = false; constructor(context: IViewContext, model: Model.Item) { this.context = context; @@ -172,12 +171,12 @@ export class ViewItem implements IViewItem { } public get element(): HTMLElement { - return this.row && this.row.element; + return (this.row && this.row.element)!; } - private _templateId: string; + private _templateId: string | undefined; private get templateId(): string { - return this._templateId || (this._templateId = (this.context.renderer.getTemplateId && this.context.renderer.getTemplateId(this.context.tree, this.model.getElement()))); + return this._templateId || (this._templateId = (this.context.renderer!.getTemplateId && this.context.renderer!.getTemplateId(this.context.tree, this.model.getElement()))); } public addClass(name: string): void { @@ -208,7 +207,7 @@ export class ViewItem implements IViewItem { // ARIA this.element.setAttribute('role', 'treeitem'); - const accessibility = this.context.accessibilityProvider; + const accessibility = this.context.accessibilityProvider!; const ariaLabel = accessibility.getAriaLabel(this.context.tree, this.model.getElement()); if (ariaLabel) { this.element.setAttribute('aria-label', ariaLabel); @@ -234,18 +233,17 @@ export class ViewItem implements IViewItem { this.element.setAttribute('aria-level', String(this.model.getDepth())); if (this.context.options.paddingOnRow) { - this.element.style.paddingLeft = this.context.options.twistiePixels + ((this.model.getDepth() - 1) * this.context.options.indentPixels) + 'px'; + this.element.style.paddingLeft = this.context.options.twistiePixels! + ((this.model.getDepth() - 1) * this.context.options.indentPixels!) + 'px'; } else { - this.element.style.paddingLeft = ((this.model.getDepth() - 1) * this.context.options.indentPixels) + 'px'; - (this.row.element.firstElementChild).style.paddingLeft = this.context.options.twistiePixels + 'px'; + this.element.style.paddingLeft = ((this.model.getDepth() - 1) * this.context.options.indentPixels!) + 'px'; + (this.row!.element!.firstElementChild).style.paddingLeft = this.context.options.twistiePixels + 'px'; } - let uri = this.context.dnd.getDragURI(this.context.tree, this.model.getElement()); + let uri = this.context.dnd!.getDragURI(this.context.tree, this.model.getElement()); if (uri !== this.uri) { if (this.unbindDragStart) { this.unbindDragStart.dispose(); - this.unbindDragStart = null; } if (uri) { @@ -260,10 +258,10 @@ export class ViewItem implements IViewItem { } if (!skipUserRender && this.element) { - let paddingLeft: number | undefined; + let paddingLeft: number = 0; if (this.context.horizontalScrolling) { const style = window.getComputedStyle(this.element); - paddingLeft = parseFloat(style.paddingLeft); + paddingLeft = parseFloat(style.paddingLeft!); } if (this.context.horizontalScrolling) { @@ -271,7 +269,7 @@ export class ViewItem implements IViewItem { } try { - this.context.renderer.renderElement(this.context.tree, this.model.getElement(), this.templateId, this.row.templateData); + this.context.renderer!.renderElement(this.context.tree, this.model.getElement(), this.templateId, this.row!.templateData); } catch (err) { console.error('Tree usage error: exception while rendering element'); console.error(err); @@ -290,13 +288,13 @@ export class ViewItem implements IViewItem { } const style = window.getComputedStyle(this.element); - const paddingLeft = parseFloat(style.paddingLeft); + const paddingLeft = parseFloat(style.paddingLeft!); this.element.style.width = 'fit-content'; this.width = DOM.getContentWidth(this.element) + paddingLeft; this.element.style.width = ''; } - public insertInDOM(container: HTMLElement, afterElement: HTMLElement): void { + public insertInDOM(container: HTMLElement, afterElement: HTMLElement | null): void { if (!this.row) { this.row = this.context.cache.alloc(this.templateId); @@ -327,10 +325,7 @@ export class ViewItem implements IViewItem { return; } - if (this.unbindDragStart) { - this.unbindDragStart.dispose(); - this.unbindDragStart = null; - } + this.unbindDragStart.dispose(); this.uri = null; @@ -341,7 +336,6 @@ export class ViewItem implements IViewItem { public dispose(): void { this.row = null; - this.model = null; } } @@ -353,7 +347,7 @@ class RootViewItem extends ViewItem { this.row = { element: wrapper, templateData: null, - templateId: null + templateId: null! }; } @@ -386,7 +380,7 @@ interface IThrottledGestureEvent { translationY: number; } -function reactionEquals(one: _.IDragOverReaction, other: _.IDragOverReaction): boolean { +function reactionEquals(one: _.IDragOverReaction, other: _.IDragOverReaction | null): boolean { if (!one && !other) { return true; } else if (!one || !other) { @@ -410,11 +404,9 @@ export class TreeView extends HeightMap { private static counter: number = 0; private instance: number; - private static currentExternalDragAndDropData: _.IDragAndDropData = null; - private context: IViewContext; private modelListeners: Lifecycle.IDisposable[]; - private model: Model.TreeModel; + private model: Model.TreeModel | null = null; private viewListeners: Lifecycle.IDisposable[]; private domNode: HTMLElement; @@ -423,8 +415,8 @@ export class TreeView extends HeightMap { private treeStyler: _.ITreeStyler; private rowsContainer: HTMLElement; private scrollableElement: ScrollableElement; - private msGesture: MSGesture; - private lastPointerType: string; + private msGesture: MSGesture | undefined; + private lastPointerType: string = ''; private lastClickTimeStamp: number = 0; private horizontalScrolling: boolean; @@ -433,35 +425,35 @@ export class TreeView extends HeightMap { private lastRenderTop: number; private lastRenderHeight: number; - private inputItem: ViewItem; + private inputItem!: ViewItem; private items: { [id: string]: ViewItem; }; private isRefreshing = false; private refreshingPreviousChildrenIds: { [id: string]: string[] } = {}; - private currentDragAndDropData: _.IDragAndDropData; + private currentDragAndDropData: IDragAndDropData | null = null; private currentDropElement: any; - private currentDropElementReaction: _.IDragOverReaction; - private currentDropTarget: ViewItem; + private currentDropElementReaction!: _.IDragOverReaction; + private currentDropTarget: ViewItem | null = null; private shouldInvalidateDropReaction: boolean; - private currentDropTargets: ViewItem[]; + private currentDropTargets: ViewItem[] | null = null; private currentDropDisposable: Lifecycle.IDisposable = Lifecycle.Disposable.None; - private dragAndDropScrollInterval: number; - private dragAndDropScrollTimeout: number; - private dragAndDropMouseY: number; + private dragAndDropScrollInterval: number | null = null; + private dragAndDropScrollTimeout: number | null = null; + private dragAndDropMouseY: number | null = null; private didJustPressContextMenuKey: boolean; - private highlightedItemWasDraggable: boolean; - private onHiddenScrollTop: number; + private highlightedItemWasDraggable: boolean = false; + private onHiddenScrollTop: number | null = null; private readonly _onDOMFocus = new Emitter(); - get onDOMFocus(): Event { return this._onDOMFocus.event; } + readonly onDOMFocus: Event = this._onDOMFocus.event; private readonly _onDOMBlur = new Emitter(); - get onDOMBlur(): Event { return this._onDOMBlur.event; } + readonly onDOMBlur: Event = this._onDOMBlur.event; private readonly _onDidScroll = new Emitter(); - get onDidScroll(): Event { return this._onDidScroll.event; } + readonly onDidScroll: Event = this._onDidScroll.event; constructor(context: _.ITreeContext, container: HTMLElement) { super(); @@ -489,7 +481,6 @@ export class TreeView extends HeightMap { this.modelListeners = []; this.viewListeners = []; - this.model = null; this.items = {}; this.domNode = document.createElement('div'); @@ -499,10 +490,7 @@ export class TreeView extends HeightMap { this.styleElement = DOM.createStyleSheet(this.domNode); - this.treeStyler = context.styler; - if (!this.treeStyler) { - this.treeStyler = new DefaultTreestyler(this.styleElement, `monaco-tree-instance-${this.instance}`); - } + this.treeStyler = context.styler || new DefaultTreestyler(this.styleElement, `monaco-tree-instance-${this.instance}`); // ARIA this.domNode.setAttribute('role', 'tree'); @@ -604,8 +592,6 @@ export class TreeView extends HeightMap { this.dragAndDropScrollInterval = null; this.dragAndDropScrollTimeout = null; - this.onHiddenScrollTop = null; - this.onRowsChanged(); this.layout(); @@ -639,7 +625,7 @@ export class TreeView extends HeightMap { } public onVisible(): void { - this.scrollTop = this.onHiddenScrollTop; + this.scrollTop = this.onHiddenScrollTop!; this.onHiddenScrollTop = null; this.setupMSGesture(); } @@ -647,7 +633,7 @@ export class TreeView extends HeightMap { private setupMSGesture(): void { if ((window).MSGesture) { this.msGesture = new MSGesture(); - setTimeout(() => this.msGesture.target = this.wrapper, 100); // TODO@joh, TODO@IETeam + setTimeout(() => this.msGesture!.target = this.wrapper, 100); // TODO@joh, TODO@IETeam } } @@ -672,27 +658,6 @@ export class TreeView extends HeightMap { } } - public getFirstVisibleElement(): any { - const firstIndex = this.indexAt(this.lastRenderTop); - let item = this.itemAtIndex(firstIndex); - if (!item) { - return item; - } - - const itemMidpoint = item.top + item.height / 2; - if (itemMidpoint < this.scrollTop) { - const nextItem = this.itemAtIndex(firstIndex + 1); - item = nextItem || item; - } - - return item.model.getElement(); - } - - public getLastVisibleElement(): any { - const item = this.itemAtIndex(this.indexAt(this.lastRenderTop + this.lastRenderHeight - 1)); - return item && item.model.getElement(); - } - private render(scrollTop: number, viewHeight: number, scrollLeft: number, viewWidth: number, scrollWidth: number): void { let i: number; let stop: number; @@ -796,10 +761,10 @@ export class TreeView extends HeightMap { let lastPageIndex = this.indexAt(this.scrollTop + this.viewHeight); lastPageIndex = lastPageIndex === 0 ? 0 : lastPageIndex - 1; let lastPageElement = this.itemAtIndex(lastPageIndex).model.getElement(); - let currentlyFocusedElement = this.model.getFocus(); + let currentlyFocusedElement = this.model!.getFocus(); if (currentlyFocusedElement !== lastPageElement) { - this.model.setFocus(lastPageElement, eventPayload); + this.model!.setFocus(lastPageElement, eventPayload); } else { let previousScrollTop = this.scrollTop; this.scrollTop += this.viewHeight; @@ -824,10 +789,10 @@ export class TreeView extends HeightMap { } let firstPageElement = this.itemAtIndex(firstPageIndex).model.getElement(); - let currentlyFocusedElement = this.model.getFocus(); + let currentlyFocusedElement = this.model!.getFocus(); if (currentlyFocusedElement !== firstPageElement) { - this.model.setFocus(firstPageElement, eventPayload); + this.model!.setFocus(firstPageElement, eventPayload); } else { let previousScrollTop = this.scrollTop; this.scrollTop -= this.viewHeight; @@ -919,7 +884,7 @@ export class TreeView extends HeightMap { if (!e.isNested) { let childrenIds: string[] = []; let navigator = item.getNavigator(); - let childItem: Model.Item; + let childItem: Model.Item | null; while (childItem = navigator.next()) { childrenIds.push(childItem.id); @@ -946,15 +911,15 @@ export class TreeView extends HeightMap { let previousChildrenIds = this.refreshingPreviousChildrenIds[item.id]; let afterModelItems: Model.Item[] = []; let navigator = item.getNavigator(); - let childItem: Model.Item; + let childItem: Model.Item | null; while (childItem = navigator.next()) { afterModelItems.push(childItem); } let skipDiff = Math.abs(previousChildrenIds.length - afterModelItems.length) > 1000; - let diff: Diff.IDiffChange[]; - let doToInsertItemsAlreadyExist: boolean; + let diff: Diff.IDiffChange[] = []; + let doToInsertItemsAlreadyExist: boolean = false; if (!skipDiff) { const lcs = new Diff.LcsDiff( @@ -989,15 +954,14 @@ export class TreeView extends HeightMap { // 50 is an optimization number, at some point we're better off // just replacing everything if (!skipDiff && !doToInsertItemsAlreadyExist && diff.length < 50) { - for (let i = 0, len = diff.length; i < len; i++) { - const diffChange = diff[i]; + for (const diffChange of diff) { if (diffChange.originalLength > 0) { this.onRemoveItems(new ArrayIterator(previousChildrenIds, diffChange.originalStart, diffChange.originalStart + diffChange.originalLength)); } if (diffChange.modifiedLength > 0) { - let beforeItem = afterModelItems[diffChange.modifiedStart - 1] || item; + let beforeItem: Model.Item | null = afterModelItems[diffChange.modifiedStart - 1] || item; beforeItem = beforeItem.getDepth() > 0 ? beforeItem : null; this.onInsertItems(new ArrayIterator(afterModelItems, diffChange.modifiedStart, diffChange.modifiedStart + diffChange.modifiedLength), beforeItem ? beforeItem.id : null); @@ -1037,7 +1001,7 @@ export class TreeView extends HeightMap { if (viewItem) { viewItem.expanded = true; - let height = this.onInsertItems(item.getNavigator(), item.id); + let height = this.onInsertItems(item.getNavigator(), item.id) || 0; let scrollTop = this.scrollTop; if (viewItem.top + viewItem.height <= this.scrollTop) { @@ -1058,31 +1022,6 @@ export class TreeView extends HeightMap { } } - public updateWidth(item: Model.Item): void { - if (!item || !item.isVisible()) { - return; - } - - const viewItem = this.items[item.id]; - - if (!viewItem) { - return; - } - - viewItem.updateWidth(); - this.updateScrollWidth(); - } - - public getRelativeTop(item: Model.Item): number { - if (item && item.isVisible()) { - let viewItem = this.items[item.id]; - if (viewItem) { - return (viewItem.top - this.scrollTop) / (this.viewHeight - viewItem.height); - } - } - return -1; - } - private onItemReveal(e: Model.IItemRevealEvent): void { let item = e.item; let relativeTop = e.relativeTop; @@ -1214,11 +1153,11 @@ export class TreeView extends HeightMap { } this.lastClickTimeStamp = Date.now(); - this.context.controller.onClick(this.context.tree, item.model.getElement(), event); + this.context.controller!.onClick(this.context.tree, item.model.getElement(), event); } private onMouseMiddleClick(e: MouseEvent): void { - if (!this.context.controller.onMouseMiddleClick) { + if (!this.context.controller!.onMouseMiddleClick!) { return; } @@ -1228,13 +1167,13 @@ export class TreeView extends HeightMap { if (!item) { return; } - this.context.controller.onMouseMiddleClick(this.context.tree, item.model.getElement(), event); + this.context.controller!.onMouseMiddleClick!(this.context.tree, item.model.getElement(), event); } private onMouseDown(e: MouseEvent): void { this.didJustPressContextMenuKey = false; - if (!this.context.controller.onMouseDown) { + if (!this.context.controller!.onMouseDown!) { return; } @@ -1254,11 +1193,11 @@ export class TreeView extends HeightMap { return; } - this.context.controller.onMouseDown(this.context.tree, item.model.getElement(), event); + this.context.controller!.onMouseDown!(this.context.tree, item.model.getElement(), event); } private onMouseUp(e: MouseEvent): void { - if (!this.context.controller.onMouseUp) { + if (!this.context.controller!.onMouseUp!) { return; } @@ -1278,7 +1217,7 @@ export class TreeView extends HeightMap { return; } - this.context.controller.onMouseUp(this.context.tree, item.model.getElement(), event); + this.context.controller!.onMouseUp!(this.context.tree, item.model.getElement(), event); } private onTap(e: Touch.GestureEvent): void { @@ -1288,7 +1227,7 @@ export class TreeView extends HeightMap { return; } - this.context.controller.onTap(this.context.tree, item.model.getElement(), e); + this.context.controller!.onTap(this.context.tree, item.model.getElement(), e); } private onTouchChange(event: Touch.GestureEvent): void { @@ -1308,16 +1247,16 @@ export class TreeView extends HeightMap { this.didJustPressContextMenuKey = false; let keyboardEvent = new Keyboard.StandardKeyboardEvent(event); - element = this.model.getFocus(); + element = this.model!.getFocus(); let position: DOM.IDomNodePagePosition; if (!element) { - element = this.model.getInput(); + element = this.model!.getInput(); position = DOM.getDomNodePagePosition(this.inputItem.element); } else { - let id = this.context.dataSource.getId(this.context.tree, element); - let viewItem = this.items[id]; + const id = this.context.dataSource.getId(this.context.tree, element); + const viewItem = this.items[id!]; position = DOM.getDomNodePagePosition(viewItem.element); } @@ -1335,7 +1274,7 @@ export class TreeView extends HeightMap { resultEvent = new _.MouseContextMenuEvent(mouseEvent); } - this.context.controller.onContextMenu(this.context.tree, element, resultEvent); + this.context.controller!.onContextMenu(this.context.tree, element, resultEvent); } private onKeyDown(e: KeyboardEvent): void { @@ -1352,7 +1291,7 @@ export class TreeView extends HeightMap { event.stopPropagation(); } - this.context.controller.onKeyDown(this.context.tree, event); + this.context.controller!.onKeyDown(this.context.tree, event); } private onKeyUp(e: KeyboardEvent): void { @@ -1361,16 +1300,16 @@ export class TreeView extends HeightMap { } this.didJustPressContextMenuKey = false; - this.context.controller.onKeyUp(this.context.tree, new Keyboard.StandardKeyboardEvent(e)); + this.context.controller!.onKeyUp(this.context.tree, new Keyboard.StandardKeyboardEvent(e)); } private onDragStart(item: ViewItem, e: any): void { - if (this.model.getHighlight()) { + if (this.model!.getHighlight()) { return; } let element = item.model.getElement(); - let selection = this.model.getSelection(); + let selection = this.model!.getSelection(); let elements: any[]; if (selection.indexOf(element) > -1) { @@ -1384,8 +1323,8 @@ export class TreeView extends HeightMap { if (e.dataTransfer.setDragImage) { let label: string; - if (this.context.dnd.getDragLabel) { - label = this.context.dnd.getDragLabel(this.context.tree, elements); + if (this.context.dnd!.getDragLabel) { + label = this.context.dnd!.getDragLabel!(this.context.tree, elements); } else { label = String(elements.length); } @@ -1399,9 +1338,9 @@ export class TreeView extends HeightMap { } this.currentDragAndDropData = new dnd.ElementsDragAndDropData(elements); - TreeView.currentExternalDragAndDropData = new dnd.ExternalElementsDragAndDropData(elements); + StaticDND.CurrentDragAndDropData = new dnd.ExternalElementsDragAndDropData(elements); - this.context.dnd.onDragStart(this.context.tree, this.currentDragAndDropData, new Mouse.DragMouseEvent(e)); + this.context.dnd!.onDragStart(this.context.tree, this.currentDragAndDropData, new Mouse.DragMouseEvent(e)); } private setupDragAndDropScrollInterval(): void { @@ -1409,7 +1348,7 @@ export class TreeView extends HeightMap { if (!this.dragAndDropScrollInterval) { this.dragAndDropScrollInterval = window.setInterval(() => { - if (this.dragAndDropMouseY === undefined) { + if (this.dragAndDropMouseY === null) { return; } @@ -1452,6 +1391,8 @@ export class TreeView extends HeightMap { } private onDragOver(e: DragEvent): boolean { + e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome) + let event = new Mouse.DragMouseEvent(e); let viewItem = this.getItemAround(event.target); @@ -1462,7 +1403,7 @@ export class TreeView extends HeightMap { if (this.currentDropTarget) { // clear previously hovered element feedback - this.currentDropTargets.forEach(i => i.dropTarget = false); + this.currentDropTargets!.forEach(i => i.dropTarget = false); this.currentDropTargets = []; this.currentDropDisposable.dispose(); } @@ -1482,8 +1423,8 @@ export class TreeView extends HeightMap { if (!this.currentDragAndDropData) { // just started dragging - if (TreeView.currentExternalDragAndDropData) { - this.currentDragAndDropData = TreeView.currentExternalDragAndDropData; + if (StaticDND.CurrentDragAndDropData) { + this.currentDragAndDropData = StaticDND.CurrentDragAndDropData; } else { if (!event.dataTransfer.types) { return false; @@ -1493,16 +1434,16 @@ export class TreeView extends HeightMap { } } - this.currentDragAndDropData.update(event); + this.currentDragAndDropData.update((event.browserEvent as DragEvent).dataTransfer!); let element: any; - let item: Model.Item = viewItem.model; - let reaction: _.IDragOverReaction; + let item: Model.Item | null = viewItem.model; + let reaction: _.IDragOverReaction | null; // check the bubble up behavior do { - element = item ? item.getElement() : this.model.getInput(); - reaction = this.context.dnd.onDragOver(this.context.tree, this.currentDragAndDropData, element, event); + element = item ? item.getElement() : this.model!.getInput(); + reaction = this.context.dnd!.onDragOver(this.context.tree, this.currentDragAndDropData, element, event); if (!reaction || reaction.bubble !== _.DragOverBubble.BUBBLE_UP) { break; @@ -1521,7 +1462,7 @@ export class TreeView extends HeightMap { if (canDrop) { this.currentDropElement = item.getElement(); event.preventDefault(); - event.dataTransfer.dropEffect = reaction.effect === _.DragOverEffect.COPY ? 'copy' : 'move'; + event.dataTransfer.dropEffect = reaction!.effect === _.DragOverEffect.COPY ? 'copy' : 'move'; } else { this.currentDropElement = null; } @@ -1535,35 +1476,35 @@ export class TreeView extends HeightMap { this.shouldInvalidateDropReaction = false; if (this.currentDropTarget) { - this.currentDropTargets.forEach(i => i.dropTarget = false); + this.currentDropTargets!.forEach(i => i.dropTarget = false); this.currentDropTargets = []; this.currentDropDisposable.dispose(); } this.currentDropTarget = currentDropTarget; - this.currentDropElementReaction = reaction; + this.currentDropElementReaction = reaction!; if (canDrop) { // setup hover feedback for drop target if (this.currentDropTarget) { this.currentDropTarget.dropTarget = true; - this.currentDropTargets.push(this.currentDropTarget); + this.currentDropTargets!.push(this.currentDropTarget); } - if (reaction.bubble === _.DragOverBubble.BUBBLE_DOWN) { + if (reaction!.bubble === _.DragOverBubble.BUBBLE_DOWN) { let nav = item.getNavigator(); - let child: Model.Item; + let child: Model.Item | null; while (child = nav.next()) { viewItem = this.items[child.id]; if (viewItem) { viewItem.dropTarget = true; - this.currentDropTargets.push(viewItem); + this.currentDropTargets!.push(viewItem); } } } - if (reaction.autoExpand) { + if (reaction!.autoExpand) { const timeoutPromise = timeout(500); this.currentDropDisposable = Lifecycle.toDisposable(() => timeoutPromise.cancel()); @@ -1581,8 +1522,8 @@ export class TreeView extends HeightMap { if (this.currentDropElement) { let event = new Mouse.DragMouseEvent(e); event.preventDefault(); - this.currentDragAndDropData.update(event); - this.context.dnd.drop(this.context.tree, this.currentDragAndDropData, this.currentDropElement, event); + this.currentDragAndDropData!.update((event.browserEvent as DragEvent).dataTransfer!); + this.context.dnd!.drop(this.context.tree, this.currentDragAndDropData!, this.currentDropElement, event); this.onDragEnd(e); } this.cancelDragAndDropScrollInterval(); @@ -1590,7 +1531,7 @@ export class TreeView extends HeightMap { private onDragEnd(e: DragEvent): void { if (this.currentDropTarget) { - this.currentDropTargets.forEach(i => i.dropTarget = false); + this.currentDropTargets!.forEach(i => i.dropTarget = false); this.currentDropTargets = []; } @@ -1598,7 +1539,7 @@ export class TreeView extends HeightMap { this.cancelDragAndDropScrollInterval(); this.currentDragAndDropData = null; - TreeView.currentExternalDragAndDropData = null; + StaticDND.CurrentDragAndDropData = undefined; this.currentDropElement = null; this.currentDropTarget = null; this.dragAndDropMouseY = null; @@ -1682,21 +1623,24 @@ export class TreeView extends HeightMap { return item.top < this.lastRenderTop + this.lastRenderHeight && item.top + item.height > this.lastRenderTop; } - private getItemAround(element: HTMLElement): ViewItem { + private getItemAround(element: HTMLElement): ViewItem | undefined { let candidate: ViewItem = this.inputItem; + let el: HTMLElement | null = element; + do { - if ((element)[TreeView.BINDING]) { - candidate = (element)[TreeView.BINDING]; + if ((el)[TreeView.BINDING]) { + candidate = (el)[TreeView.BINDING]; } - if (element === this.wrapper || element === this.domNode) { + if (el === this.wrapper || el === this.domNode) { return candidate; } - if (element === this.scrollableElement.getDomNode() || element === document.body) { - return null; + if (el === this.scrollableElement.getDomNode() || el === document.body) { + return undefined; } - } while (element = element.parentElement); + } while (el = el.parentElement); + return undefined; } @@ -1714,7 +1658,6 @@ export class TreeView extends HeightMap { this.scrollableElement.dispose(); this.releaseModel(); - this.modelListeners = null; this.viewListeners = Lifecycle.dispose(this.viewListeners); @@ -1724,16 +1667,13 @@ export class TreeView extends HeightMap { if (this.domNode.parentNode) { this.domNode.parentNode.removeChild(this.domNode); } - this.domNode = null; if (this.items) { Object.keys(this.items).forEach(key => this.items[key].removeFromDOM()); - this.items = null; } if (this.context.cache) { this.context.cache.dispose(); - this.context.cache = null; } super.dispose(); diff --git a/src/vs/base/parts/tree/browser/treeViewModel.ts b/src/vs/base/parts/tree/browser/treeViewModel.ts index 07f0c852e3a..823f0bb0a9d 100644 --- a/src/vs/base/parts/tree/browser/treeViewModel.ts +++ b/src/vs/base/parts/tree/browser/treeViewModel.ts @@ -15,21 +15,16 @@ export interface IViewItem { export class HeightMap { - private heightMap: IViewItem[]; - private indexes: { [item: string]: number; }; + private heightMap: IViewItem[] = []; + private indexes: { [item: string]: number; } = {}; - constructor() { - this.heightMap = []; - this.indexes = {}; - } - - public getContentHeight(): number { + getContentHeight(): number { let last = this.heightMap[this.heightMap.length - 1]; return !last ? 0 : last.top + last.height; } - public onInsertItems(iterator: INextIterator, afterItemId: string | null = null): number { - let item: Item; + onInsertItems(iterator: INextIterator, afterItemId: string | null = null): number | undefined { + let item: Item | null = null; let viewItem: IViewItem; let i: number, j: number; let totalSize: number; @@ -82,16 +77,16 @@ export class HeightMap { return sizeDiff; } - public onInsertItem(item: IViewItem): void { + onInsertItem(item: IViewItem): void { // noop } // Contiguous items - public onRemoveItems(iterator: INextIterator): void { - let itemId: string; + onRemoveItems(iterator: INextIterator): void { + let itemId: string | null = null; let viewItem: IViewItem; let startIndex: number | null = null; - let i: number; + let i = 0; let sizeDiff = 0; while (itemId = iterator.next()) { @@ -112,7 +107,7 @@ export class HeightMap { } } - if (sizeDiff === 0) { + if (sizeDiff === 0 || startIndex === null) { return; } @@ -126,18 +121,18 @@ export class HeightMap { } } - public onRemoveItem(item: IViewItem): void { + onRemoveItem(item: IViewItem): void { // noop } - public onRefreshItemSet(items: Item[]): void { + onRefreshItemSet(items: Item[]): void { let sortedItems = items.sort((a, b) => this.indexes[a.id] - this.indexes[b.id]); this.onRefreshItems(new ArrayIterator(sortedItems)); } // Ordered, but not necessarily contiguous items - public onRefreshItems(iterator: INextIterator): void { - let item: Item; + onRefreshItems(iterator: INextIterator): void { + let item: Item | null = null; let viewItem: IViewItem; let newHeight: number; let i: number, j: number | null = null; @@ -171,19 +166,19 @@ export class HeightMap { } } - public onRefreshItem(item: IViewItem, needsRender: boolean = false): void { + onRefreshItem(item: IViewItem, needsRender: boolean = false): void { // noop } - public itemsCount(): number { + itemsCount(): number { return this.heightMap.length; } - public itemAt(position: number): string { + itemAt(position: number): string { return this.heightMap[this.indexAt(position)].model.id; } - public withItemsInRange(start: number, end: number, fn: (item: string) => void): void { + withItemsInRange(start: number, end: number, fn: (item: string) => void): void { start = this.indexAt(start); end = this.indexAt(end); for (let i = start; i <= end; i++) { @@ -191,7 +186,7 @@ export class HeightMap { } } - public indexAt(position: number): number { + indexAt(position: number): number { let left = 0; let right = this.heightMap.length; let center: number; @@ -217,15 +212,15 @@ export class HeightMap { return this.heightMap.length; } - public indexAfter(position: number): number { + indexAfter(position: number): number { return Math.min(this.indexAt(position) + 1, this.heightMap.length); } - public itemAtIndex(index: number): IViewItem { + itemAtIndex(index: number): IViewItem { return this.heightMap[index]; } - public itemAfter(item: IViewItem): IViewItem { + itemAfter(item: IViewItem): IViewItem { return this.heightMap[this.indexes[item.model.id] + 1] || null; } @@ -233,8 +228,8 @@ export class HeightMap { throw new Error('not implemented'); } - public dispose(): void { - this.heightMap = null; - this.indexes = null; + dispose(): void { + this.heightMap = []; + this.indexes = {}; } } diff --git a/src/vs/base/parts/tree/test/browser/treeModel.test.ts b/src/vs/base/parts/tree/test/browser/treeModel.test.ts index 50ee814c156..5a880d99194 100644 --- a/src/vs/base/parts/tree/test/browser/treeModel.test.ts +++ b/src/vs/base/parts/tree/test/browser/treeModel.test.ts @@ -161,19 +161,19 @@ const SAMPLE: any = { }; class TestDataSource implements _.IDataSource { - public getId(tree, element): string { + public getId(tree: _.ITree, element: any): string { return element.id; } - public hasChildren(tree, element): boolean { + public hasChildren(tree: _.ITree, element: any): boolean { return !!element.children; } - public getChildren(tree, element): Promise { + public getChildren(tree: _.ITree, element: any): Promise { return Promise.resolve(element.children); } - public getParent(tree, element): Promise { + public getParent(tree: _.ITree, element: any): Promise { throw new Error('Not implemented'); } } @@ -700,13 +700,13 @@ suite('TreeModel - Expansion', () => { class TestFilter implements _.IFilter { - public fn: (any) => boolean; + public fn: (element: any) => boolean; constructor() { this.fn = () => true; } - public isVisible(tree, element): boolean { + public isVisible(tree: _.ITree, element: any): boolean { return this.fn(element); } } @@ -1092,39 +1092,39 @@ class DynamicModel implements _.IDataSource { this.promiseFactory = null; } - public addChild(parent, child): void { + public addChild(parent: string, child: string): void { if (!this.data[parent]) { this.data[parent] = []; } this.data[parent].push(child); } - public removeChild(parent, child): void { + public removeChild(parent: string, child: string): void { this.data[parent].splice(this.data[parent].indexOf(child), 1); if (this.data[parent].length === 0) { delete this.data[parent]; } } - public move(element, oldParent, newParent): void { + public move(element: string, oldParent: string, newParent: string): void { this.removeChild(oldParent, element); this.addChild(newParent, element); } - public rename(parent, oldName, newName): void { + public rename(parent: string, oldName: string, newName: string): void { this.removeChild(parent, oldName); this.addChild(parent, newName); } - public getId(tree, element): string { + public getId(tree: _.ITree, element: any): string { return element; } - public hasChildren(tree, element): boolean { + public hasChildren(tree: _.ITree, element: any): boolean { return !!this.data[element]; } - public getChildren(tree, element): Promise { + public getChildren(tree: _.ITree, element: any): Promise { this._onGetChildren.fire(element); const result = this.promiseFactory ? this.promiseFactory() : Promise.resolve(null); return result.then(() => { @@ -1133,7 +1133,7 @@ class DynamicModel implements _.IDataSource { }); } - public getParent(tree, element): Promise { + public getParent(tree: _.ITree, element: any): Promise { throw new Error('Not implemented'); } } @@ -1395,7 +1395,7 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(getTimes, 2); assert.equal(gotTimes, 1); - let p2Complete; + let p2Complete: () => void; dataModel.promiseFactory = () => { return new Promise((c) => { p2Complete = c; }); }; const p2 = model.refresh('father'); @@ -1412,7 +1412,7 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(getTimes, 3); assert.equal(gotTimes, 2); - p2Complete(); + p2Complete!(); // all good assert.equal(refreshTimes, 5); // (+1) second son request diff --git a/src/vs/base/parts/tree/test/browser/treeViewModel.test.ts b/src/vs/base/parts/tree/test/browser/treeViewModel.test.ts index 5c5bdd39291..97c2846ebb6 100644 --- a/src/vs/base/parts/tree/test/browser/treeViewModel.test.ts +++ b/src/vs/base/parts/tree/test/browser/treeViewModel.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { ArrayIterator } from 'vs/base/common/iterator'; import { HeightMap, IViewItem } from 'vs/base/parts/tree/browser/treeViewModel'; -function makeItem(id, height): any { +function makeItem(id: any, height: any): any { return { id: id, getHeight: function () { return height; }, diff --git a/src/vs/base/test/browser/comparers.test.ts b/src/vs/base/test/browser/comparers.test.ts index df74e2bbfa2..369f160803b 100644 --- a/src/vs/base/test/browser/comparers.test.ts +++ b/src/vs/base/test/browser/comparers.test.ts @@ -3,23 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { compareFileNames, compareFileExtensions, setFileNameComparer } from 'vs/base/common/comparers'; +import { compareFileNames, compareFileExtensions } from 'vs/base/common/comparers'; import * as assert from 'assert'; -import { IdleValue } from 'vs/base/common/async'; suite('Comparers', () => { test('compareFileNames', () => { - // Setup Intl - setFileNameComparer(new IdleValue(() => { - const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }); - return { - collator: collator, - collatorIsNumeric: collator.resolvedOptions().numeric - }; - })); - assert(compareFileNames(null, null) === 0, 'null should be equal'); assert(compareFileNames(null, 'abc') < 0, 'null should be come before real values'); assert(compareFileNames('', '') === 0, 'empty should be equal'); @@ -35,15 +25,6 @@ suite('Comparers', () => { test('compareFileExtensions', () => { - // Setup Intl - setFileNameComparer(new IdleValue(() => { - const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }); - return { - collator: collator, - collatorIsNumeric: collator.resolvedOptions().numeric - }; - })); - assert(compareFileExtensions(null, null) === 0, 'null should be equal'); assert(compareFileExtensions(null, '.abc') < 0, 'null should come before real files'); assert(compareFileExtensions(null, 'abc') < 0, 'null should come before real files without extension'); @@ -66,4 +47,4 @@ suite('Comparers', () => { assert(compareFileExtensions('file2.ext2', 'file1.ext10') < 0, 'extensions with numbers should be in numerical order, not alphabetical order'); assert(compareFileExtensions('file.ext01', 'file.ext1') < 0, 'extensions with equal numbers should be in alphabetical order'); }); -}); \ No newline at end of file +}); diff --git a/src/vs/base/test/browser/highlightedLabel.test.ts b/src/vs/base/test/browser/highlightedLabel.test.ts index 4fbab5b9614..c658c835c04 100644 --- a/src/vs/base/test/browser/highlightedLabel.test.ts +++ b/src/vs/base/test/browser/highlightedLabel.test.ts @@ -12,10 +12,6 @@ suite('HighlightedLabel', () => { label = new HighlightedLabel(document.createElement('div'), true); }); - teardown(() => { - label.dispose(); - }); - test('empty label', function () { assert.equal(label.element.innerHTML, ''); }); diff --git a/src/vs/base/test/browser/htmlContent.test.ts b/src/vs/base/test/browser/htmlContent.test.ts index 6035010b3b4..d5dec0729d9 100644 --- a/src/vs/base/test/browser/htmlContent.test.ts +++ b/src/vs/base/test/browser/htmlContent.test.ts @@ -5,8 +5,19 @@ import * as assert from 'assert'; import * as marked from 'vs/base/common/marked/marked'; import { renderMarkdown, renderText, renderFormattedText } from 'vs/base/browser/htmlContentRenderer'; +import { DisposableStore } from 'vs/base/common/lifecycle'; suite('HtmlContent', () => { + const store = new DisposableStore(); + + setup(() => { + store.clear(); + }); + + teardown(() => { + store.clear(); + }); + test('render simple element', () => { let result: HTMLElement = renderText('testing'); @@ -55,7 +66,7 @@ suite('HtmlContent', () => { assert.strictEqual(content, '0'); callbackCalled = true; }, - disposeables: [] + disposeables: store } }); assert.strictEqual(result.innerHTML, 'action'); @@ -74,7 +85,7 @@ suite('HtmlContent', () => { assert.strictEqual(content, '0'); callbackCalled = true; }, - disposeables: [] + disposeables: store } }); assert.strictEqual(result.innerHTML, 'action'); diff --git a/src/vs/base/test/browser/ui/grid/grid.test.ts b/src/vs/base/test/browser/ui/grid/grid.test.ts index 58729c4fe51..3c2b1b4ec44 100644 --- a/src/vs/base/test/browser/ui/grid/grid.test.ts +++ b/src/vs/base/test/browser/ui/grid/grid.test.ts @@ -8,6 +8,15 @@ import { Direction, getRelativeLocation, Orientation, SerializableGrid, ISeriali import { TestView, nodesToArrays } from './util'; import { deepClone } from 'vs/base/common/objects'; +// Simple example: +// +-----+---------------+ +// | 4 | 2 | +// +-----+---------+-----+ +// | 1 | | +// +---------------+ 3 | +// | 5 | | +// +---------------+-----+ + suite('Grid', function () { let container: HTMLElement; @@ -469,7 +478,11 @@ class TestViewDeserializer implements IViewDeserializer { } getView(id: string): TestSerializableView { - return this.views.get(id); + const view = this.views.get(id); + if (!view) { + throw new Error('Unknown view'); + } + return view; } } @@ -621,12 +634,6 @@ suite('SerializableGrid', function () { assert.deepEqual(nodesToArrays(grid2.getViews()), [[view4Copy, view2Copy], [[view1Copy, view5Copy], view3Copy]]); - assert.deepEqual(view1Copy.size, [50, 50]); - assert.deepEqual(view2Copy.size, [50, 50]); - assert.deepEqual(view3Copy.size, [50, 100]); - assert.deepEqual(view4Copy.size, [50, 50]); - assert.deepEqual(view5Copy.size, [50, 50]); - grid2.layout(800, 600); assert.deepEqual(view1Copy.size, [600, 300]); @@ -794,4 +801,222 @@ suite('SerializableGrid', function () { height: 1 }); }); + + test('serialize should store visibility and previous size', function () { + const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const grid = new SerializableGrid(view1); + container.appendChild(grid.element); + grid.layout(800, 600); + + const view2 = new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + grid.addView(view2, 200, view1, Direction.Up); + + const view3 = new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + grid.addView(view3, 200, view1, Direction.Right); + + const view4 = new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + grid.addView(view4, 200, view2, Direction.Left); + + const view5 = new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + grid.addView(view5, 100, view1, Direction.Down); + + assert.deepEqual(view1.size, [600, 300]); + assert.deepEqual(view2.size, [600, 200]); + assert.deepEqual(view3.size, [200, 400]); + assert.deepEqual(view4.size, [200, 200]); + assert.deepEqual(view5.size, [600, 100]); + + grid.setViewVisible(view5, false); + + assert.deepEqual(view1.size, [600, 400]); + assert.deepEqual(view2.size, [600, 200]); + assert.deepEqual(view3.size, [200, 400]); + assert.deepEqual(view4.size, [200, 200]); + assert.deepEqual(view5.size, [600, 0]); + + const json = grid.serialize(); + assert.deepEqual(json, { + orientation: 0, + width: 800, + height: 600, + root: { + type: 'branch', + data: [ + { + type: 'branch', + data: [ + { type: 'leaf', data: { name: 'view4' }, size: 200 }, + { type: 'leaf', data: { name: 'view2' }, size: 600 } + ], + size: 200 + }, + { + type: 'branch', + data: [ + { + type: 'branch', + data: [ + { type: 'leaf', data: { name: 'view1' }, size: 400 }, + { type: 'leaf', data: { name: 'view5' }, size: 100, visible: false } + ], + size: 600 + }, + { type: 'leaf', data: { name: 'view3' }, size: 200 } + ], + size: 400 + } + ], + size: 800 + } + }); + + grid.dispose(); + + const deserializer = new TestViewDeserializer(); + const grid2 = SerializableGrid.deserialize(json, deserializer); + + const view1Copy = deserializer.getView('view1'); + const view2Copy = deserializer.getView('view2'); + const view3Copy = deserializer.getView('view3'); + const view4Copy = deserializer.getView('view4'); + const view5Copy = deserializer.getView('view5'); + + assert.deepEqual(nodesToArrays(grid2.getViews()), [[view4Copy, view2Copy], [[view1Copy, view5Copy], view3Copy]]); + + grid2.layout(800, 600); + assert.deepEqual(view1Copy.size, [600, 400]); + assert.deepEqual(view2Copy.size, [600, 200]); + assert.deepEqual(view3Copy.size, [200, 400]); + assert.deepEqual(view4Copy.size, [200, 200]); + assert.deepEqual(view5Copy.size, [600, 0]); + + assert.deepEqual(grid2.isViewVisible(view1Copy), true); + assert.deepEqual(grid2.isViewVisible(view2Copy), true); + assert.deepEqual(grid2.isViewVisible(view3Copy), true); + assert.deepEqual(grid2.isViewVisible(view4Copy), true); + assert.deepEqual(grid2.isViewVisible(view5Copy), false); + + grid2.setViewVisible(view5Copy, true); + + assert.deepEqual(view1Copy.size, [600, 300]); + assert.deepEqual(view2Copy.size, [600, 200]); + assert.deepEqual(view3Copy.size, [200, 400]); + assert.deepEqual(view4Copy.size, [200, 200]); + assert.deepEqual(view5Copy.size, [600, 100]); + + assert.deepEqual(grid2.isViewVisible(view1Copy), true); + assert.deepEqual(grid2.isViewVisible(view2Copy), true); + assert.deepEqual(grid2.isViewVisible(view3Copy), true); + assert.deepEqual(grid2.isViewVisible(view4Copy), true); + assert.deepEqual(grid2.isViewVisible(view5Copy), true); + }); + + test('serialize should store visibility and previous size even for first leaf', function () { + const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const grid = new SerializableGrid(view1); + container.appendChild(grid.element); + grid.layout(800, 600); + + const view2 = new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + grid.addView(view2, 200, view1, Direction.Up); + + const view3 = new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + grid.addView(view3, 200, view1, Direction.Right); + + const view4 = new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + grid.addView(view4, 200, view2, Direction.Left); + + const view5 = new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + grid.addView(view5, 100, view1, Direction.Down); + + assert.deepEqual(view1.size, [600, 300]); + assert.deepEqual(view2.size, [600, 200]); + assert.deepEqual(view3.size, [200, 400]); + assert.deepEqual(view4.size, [200, 200]); + assert.deepEqual(view5.size, [600, 100]); + + grid.setViewVisible(view4, false); + + assert.deepEqual(view1.size, [600, 300]); + assert.deepEqual(view2.size, [800, 200]); + assert.deepEqual(view3.size, [200, 400]); + assert.deepEqual(view4.size, [0, 200]); + assert.deepEqual(view5.size, [600, 100]); + + const json = grid.serialize(); + assert.deepEqual(json, { + orientation: 0, + width: 800, + height: 600, + root: { + type: 'branch', + data: [ + { + type: 'branch', + data: [ + { type: 'leaf', data: { name: 'view4' }, size: 200, visible: false }, + { type: 'leaf', data: { name: 'view2' }, size: 800 } + ], + size: 200 + }, + { + type: 'branch', + data: [ + { + type: 'branch', + data: [ + { type: 'leaf', data: { name: 'view1' }, size: 300 }, + { type: 'leaf', data: { name: 'view5' }, size: 100 } + ], + size: 600 + }, + { type: 'leaf', data: { name: 'view3' }, size: 200 } + ], + size: 400 + } + ], + size: 800 + } + }); + + grid.dispose(); + + const deserializer = new TestViewDeserializer(); + const grid2 = SerializableGrid.deserialize(json, deserializer); + + const view1Copy = deserializer.getView('view1'); + const view2Copy = deserializer.getView('view2'); + const view3Copy = deserializer.getView('view3'); + const view4Copy = deserializer.getView('view4'); + const view5Copy = deserializer.getView('view5'); + + assert.deepEqual(nodesToArrays(grid2.getViews()), [[view4Copy, view2Copy], [[view1Copy, view5Copy], view3Copy]]); + + grid2.layout(800, 600); + assert.deepEqual(view1Copy.size, [600, 300]); + assert.deepEqual(view2Copy.size, [800, 200]); + assert.deepEqual(view3Copy.size, [200, 400]); + assert.deepEqual(view4Copy.size, [0, 200]); + assert.deepEqual(view5Copy.size, [600, 100]); + + assert.deepEqual(grid2.isViewVisible(view1Copy), true); + assert.deepEqual(grid2.isViewVisible(view2Copy), true); + assert.deepEqual(grid2.isViewVisible(view3Copy), true); + assert.deepEqual(grid2.isViewVisible(view4Copy), false); + assert.deepEqual(grid2.isViewVisible(view5Copy), true); + + grid2.setViewVisible(view4Copy, true); + + assert.deepEqual(view1Copy.size, [600, 300]); + assert.deepEqual(view2Copy.size, [600, 200]); + assert.deepEqual(view3Copy.size, [200, 400]); + assert.deepEqual(view4Copy.size, [200, 200]); + assert.deepEqual(view5Copy.size, [600, 100]); + + assert.deepEqual(grid2.isViewVisible(view1Copy), true); + assert.deepEqual(grid2.isViewVisible(view2Copy), true); + assert.deepEqual(grid2.isViewVisible(view3Copy), true); + assert.deepEqual(grid2.isViewVisible(view4Copy), true); + assert.deepEqual(grid2.isViewVisible(view5Copy), true); + }); }); diff --git a/src/vs/base/test/browser/ui/grid/gridview.test.ts b/src/vs/base/test/browser/ui/grid/gridview.test.ts index 3d000d85a67..78cc44cc76a 100644 --- a/src/vs/base/test/browser/ui/grid/gridview.test.ts +++ b/src/vs/base/test/browser/ui/grid/gridview.test.ts @@ -22,7 +22,7 @@ suite('Gridview', function () { }); test('empty gridview is empty', function () { - assert.deepEqual(nodesToArrays(gridview.getViews()), []); + assert.deepEqual(nodesToArrays(gridview.getView()), []); gridview.dispose(); }); @@ -43,7 +43,7 @@ suite('Gridview', function () { gridview.addView(views[1], 200, [1]); gridview.addView(views[2], 200, [2]); - assert.deepEqual(nodesToArrays(gridview.getViews()), views); + assert.deepEqual(nodesToArrays(gridview.getView()), views); gridview.dispose(); }); @@ -59,10 +59,10 @@ suite('Gridview', function () { ]; gridview.addView(views[0] as IView, 200, [0]); - gridview.addView(views[1][0] as IView, 200, [1]); - gridview.addView(views[1][1] as IView, 200, [1, 1]); + gridview.addView((views[1] as TestView[])[0] as IView, 200, [1]); + gridview.addView((views[1] as TestView[])[1] as IView, 200, [1, 1]); - assert.deepEqual(nodesToArrays(gridview.getViews()), views); + assert.deepEqual(nodesToArrays(gridview.getView()), views); gridview.dispose(); }); @@ -71,35 +71,35 @@ suite('Gridview', function () { const view1 = new TestView(20, 20, 20, 20); gridview.addView(view1 as IView, 200, [0]); - assert.deepEqual(nodesToArrays(gridview.getViews()), [view1]); + assert.deepEqual(nodesToArrays(gridview.getView()), [view1]); const view2 = new TestView(20, 20, 20, 20); gridview.addView(view2 as IView, 200, [1]); - assert.deepEqual(nodesToArrays(gridview.getViews()), [view1, view2]); + assert.deepEqual(nodesToArrays(gridview.getView()), [view1, view2]); const view3 = new TestView(20, 20, 20, 20); gridview.addView(view3 as IView, 200, [1, 0]); - assert.deepEqual(nodesToArrays(gridview.getViews()), [view1, [view3, view2]]); + assert.deepEqual(nodesToArrays(gridview.getView()), [view1, [view3, view2]]); const view4 = new TestView(20, 20, 20, 20); gridview.addView(view4 as IView, 200, [1, 0, 0]); - assert.deepEqual(nodesToArrays(gridview.getViews()), [view1, [[view4, view3], view2]]); + assert.deepEqual(nodesToArrays(gridview.getView()), [view1, [[view4, view3], view2]]); const view5 = new TestView(20, 20, 20, 20); gridview.addView(view5 as IView, 200, [1, 0]); - assert.deepEqual(nodesToArrays(gridview.getViews()), [view1, [view5, [view4, view3], view2]]); + assert.deepEqual(nodesToArrays(gridview.getView()), [view1, [view5, [view4, view3], view2]]); const view6 = new TestView(20, 20, 20, 20); gridview.addView(view6 as IView, 200, [2]); - assert.deepEqual(nodesToArrays(gridview.getViews()), [view1, [view5, [view4, view3], view2], view6]); + assert.deepEqual(nodesToArrays(gridview.getView()), [view1, [view5, [view4, view3], view2], view6]); const view7 = new TestView(20, 20, 20, 20); gridview.addView(view7 as IView, 200, [1, 1]); - assert.deepEqual(nodesToArrays(gridview.getViews()), [view1, [view5, view7, [view4, view3], view2], view6]); + assert.deepEqual(nodesToArrays(gridview.getView()), [view1, [view5, view7, [view4, view3], view2], view6]); const view8 = new TestView(20, 20, 20, 20); gridview.addView(view8 as IView, 200, [1, 1, 0]); - assert.deepEqual(nodesToArrays(gridview.getViews()), [view1, [view5, [view8, view7], [view4, view3], view2], view6]); + assert.deepEqual(nodesToArrays(gridview.getView()), [view1, [view5, [view8, view7], [view4, view3], view2], view6]); gridview.dispose(); }); @@ -107,19 +107,19 @@ suite('Gridview', function () { test('simple layout', function () { gridview.layout(800, 600); - const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view1 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view1, 200, [0]); assert.deepEqual(view1.size, [800, 600]); assert.deepEqual(gridview.getViewSize([0]), { width: 800, height: 600 }); - const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view2 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view2, 200, [0]); assert.deepEqual(view1.size, [800, 400]); assert.deepEqual(gridview.getViewSize([1]), { width: 800, height: 400 }); assert.deepEqual(view2.size, [800, 200]); assert.deepEqual(gridview.getViewSize([0]), { width: 800, height: 200 }); - const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view3 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view3, 200, [1, 1]); assert.deepEqual(view1.size, [600, 400]); assert.deepEqual(gridview.getViewSize([1, 0]), { width: 600, height: 400 }); @@ -128,7 +128,7 @@ suite('Gridview', function () { assert.deepEqual(view3.size, [200, 400]); assert.deepEqual(gridview.getViewSize([1, 1]), { width: 200, height: 400 }); - const view4 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view4 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view4, 200, [0, 0]); assert.deepEqual(view1.size, [600, 400]); assert.deepEqual(gridview.getViewSize([1, 0]), { width: 600, height: 400 }); @@ -139,7 +139,7 @@ suite('Gridview', function () { assert.deepEqual(view4.size, [200, 200]); assert.deepEqual(gridview.getViewSize([0, 0]), { width: 200, height: 200 }); - const view5 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view5 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view5, 100, [1, 0, 1]); assert.deepEqual(view1.size, [600, 300]); assert.deepEqual(gridview.getViewSize([1, 0, 0]), { width: 600, height: 300 }); @@ -156,30 +156,30 @@ suite('Gridview', function () { test('simple layout with automatic size distribution', function () { gridview.layout(800, 600); - const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view1 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view1, Sizing.Distribute, [0]); assert.deepEqual(view1.size, [800, 600]); assert.deepEqual(gridview.getViewSize([0]), { width: 800, height: 600 }); - const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view2 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view2, Sizing.Distribute, [0]); assert.deepEqual(view1.size, [800, 300]); assert.deepEqual(view2.size, [800, 300]); - const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view3 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view3, Sizing.Distribute, [1, 1]); assert.deepEqual(view1.size, [400, 300]); assert.deepEqual(view2.size, [800, 300]); assert.deepEqual(view3.size, [400, 300]); - const view4 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view4 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view4, Sizing.Distribute, [0, 0]); assert.deepEqual(view1.size, [400, 300]); assert.deepEqual(view2.size, [400, 300]); assert.deepEqual(view3.size, [400, 300]); assert.deepEqual(view4.size, [400, 300]); - const view5 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view5 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view5, Sizing.Distribute, [1, 0, 1]); assert.deepEqual(view1.size, [400, 150]); assert.deepEqual(view2.size, [400, 300]); @@ -190,13 +190,13 @@ suite('Gridview', function () { test('addviews before layout call 1', function () { - const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view1 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view1, 200, [0]); - const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view2 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view2, 200, [0]); - const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view3 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view3, 200, [1, 1]); gridview.layout(800, 600); @@ -207,14 +207,13 @@ suite('Gridview', function () { }); test('addviews before layout call 2', function () { - - const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view1 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view1, 200, [0]); - const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view2 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view2, 200, [0]); - const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE); + const view3 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY); gridview.addView(view3, 200, [0, 0]); gridview.layout(800, 600); diff --git a/src/vs/base/test/browser/ui/grid/util.ts b/src/vs/base/test/browser/ui/grid/util.ts index 0efdc44851a..39a35736ddd 100644 --- a/src/vs/base/test/browser/ui/grid/util.ts +++ b/src/vs/base/test/browser/ui/grid/util.ts @@ -5,7 +5,8 @@ import * as assert from 'assert'; import { Emitter, Event } from 'vs/base/common/event'; -import { IView, GridNode, isGridBranchNode, } from 'vs/base/browser/ui/grid/gridview'; +import { GridNode, isGridBranchNode } from 'vs/base/browser/ui/grid/gridview'; +import { IView } from 'vs/base/browser/ui/grid/grid'; export class TestView implements IView { @@ -78,4 +79,4 @@ export function nodesToArrays(node: GridNode): any { } else { return node.view; } -} \ No newline at end of file +} diff --git a/src/vs/base/test/browser/ui/menu/menubar.test.ts b/src/vs/base/test/browser/ui/menu/menubar.test.ts new file mode 100644 index 00000000000..8bbeddcfc58 --- /dev/null +++ b/src/vs/base/test/browser/ui/menu/menubar.test.ts @@ -0,0 +1,81 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { $ } from 'vs/base/browser/dom'; +import { MenuBar } from 'vs/base/browser/ui/menu/menubar'; + +function getButtonElementByAriaLabel(menubarElement: HTMLElement, ariaLabel: string): HTMLElement | null { + let i; + for (i = 0; i < menubarElement.childElementCount; i++) { + + if (menubarElement.children[i].getAttribute('aria-label') === ariaLabel) { + return menubarElement.children[i] as HTMLElement; + } + } + + return null; +} + +function getTitleDivFromButtonDiv(menuButtonElement: HTMLElement): HTMLElement | null { + let i; + for (i = 0; i < menuButtonElement.childElementCount; i++) { + if (menuButtonElement.children[i].classList.contains('menubar-menu-title')) { + return menuButtonElement.children[i] as HTMLElement; + } + } + + return null; +} + +function getMnemonicFromTitleDiv(menuTitleDiv: HTMLElement): string | null { + let i; + for (i = 0; i < menuTitleDiv.childElementCount; i++) { + if (menuTitleDiv.children[i].tagName.toLocaleLowerCase() === 'mnemonic') { + return menuTitleDiv.children[i].textContent; + } + } + + return null; +} + +function validateMenuBarItem(menubar: MenuBar, menubarContainer: HTMLElement, label: string, readableLabel: string, mnemonic: string) { + menubar.push([ + { + actions: [], + label: label + } + ]); + + const buttonElement = getButtonElementByAriaLabel(menubarContainer, readableLabel); + assert(buttonElement !== null, `Button element not found for ${readableLabel} button.`); + + const titleDiv = getTitleDivFromButtonDiv(buttonElement!); + assert(titleDiv !== null, `Title div not found for ${readableLabel} button.`); + + const mnem = getMnemonicFromTitleDiv(titleDiv!); + assert.equal(mnem, mnemonic, 'Mnemonic not correct'); +} + +suite('Menubar', () => { + const container = $('.container'); + + const menubar = new MenuBar(container, { + enableMnemonics: true, + visibility: 'visible' + }); + + test('English File menu renders mnemonics', function () { + validateMenuBarItem(menubar, container, '&File', 'File', 'F'); + }); + + test('Russian File menu renders mnemonics', function () { + validateMenuBarItem(menubar, container, '&Файл', 'Файл', 'Ф'); + }); + + test('Chinese File menu renders mnemonics', function () { + validateMenuBarItem(menubar, container, '文件(&F)', '文件', 'F'); + }); +}); \ No newline at end of file diff --git a/src/vs/base/test/browser/ui/splitview/splitview.test.ts b/src/vs/base/test/browser/ui/splitview/splitview.test.ts index 674eb8ece90..504e665f21a 100644 --- a/src/vs/base/test/browser/ui/splitview/splitview.test.ts +++ b/src/vs/base/test/browser/ui/splitview/splitview.test.ts @@ -59,7 +59,7 @@ class TestView implements IView { } function getSashes(splitview: SplitView): Sash[] { - return (splitview as any).sashItems.map(i => i.sash) as Sash[]; + return (splitview as any).sashItems.map((i: any) => i.sash) as Sash[]; } suite('Splitview', () => { @@ -196,8 +196,8 @@ suite('Splitview', () => { splitview.resizeView(0, 70); assert.equal(view1.size, 70, 'view1 is collapsed'); - assert.equal(view2.size, 110, 'view2 is expanded'); - assert.equal(view3.size, 20, 'view3 stays the same'); + assert.equal(view2.size, 40, 'view2 stays the same'); + assert.equal(view3.size, 90, 'view3 is stretched'); splitview.resizeView(2, 40); @@ -474,10 +474,10 @@ suite('Splitview', () => { splitview.addView(view1, Sizing.Distribute); splitview.addView(view2, Sizing.Distribute); splitview.addView(view3, Sizing.Distribute); - assert.deepEqual([view1.size, view2.size, view3.size], [66, 66, 68]); + assert.deepEqual([view1.size, view2.size, view3.size], [66, 68, 66]); splitview.layout(180); - assert.deepEqual([view1.size, view2.size, view3.size], [66, 46, 68]); + assert.deepEqual([view1.size, view2.size, view3.size], [66, 48, 66]); splitview.layout(124); assert.deepEqual([view1.size, view2.size, view3.size], [66, 20, 38]); @@ -504,13 +504,13 @@ suite('Splitview', () => { splitview.addView(view1, Sizing.Distribute); splitview.addView(view2, Sizing.Distribute); splitview.addView(view3, Sizing.Distribute); - assert.deepEqual([view1.size, view2.size, view3.size], [66, 66, 68]); + assert.deepEqual([view1.size, view2.size, view3.size], [66, 68, 66]); splitview.layout(180); - assert.deepEqual([view1.size, view2.size, view3.size], [66, 46, 68]); + assert.deepEqual([view1.size, view2.size, view3.size], [66, 48, 66]); splitview.layout(132); - assert.deepEqual([view1.size, view2.size, view3.size], [44, 20, 68]); + assert.deepEqual([view1.size, view2.size, view3.size], [46, 20, 66]); splitview.layout(60); assert.deepEqual([view1.size, view2.size, view3.size], [20, 20, 20]); diff --git a/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts b/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts index 7e0fc7b847f..0e93e4bb377 100644 --- a/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts +++ b/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts @@ -91,14 +91,292 @@ suite('AsyncDataTree', function () { { id: 'ac' } ]; - await tree.refresh(root); + await tree.updateChildren(root); assert.equal(container.querySelectorAll('.monaco-list-row').length, 1); await tree.expand(_('a')); assert.equal(container.querySelectorAll('.monaco-list-row').length, 4); _('a').children = []; - await tree.refresh(root); + await tree.updateChildren(root); assert.equal(container.querySelectorAll('.monaco-list-row').length, 1); }); + + test('issue #68648', async () => { + const container = document.createElement('div'); + container.style.width = '200px'; + container.style.height = '200px'; + + const delegate = new class implements IListVirtualDelegate { + getHeight() { return 20; } + getTemplateId(element: Element): string { return 'default'; } + }; + + const renderer = new class implements ITreeRenderer { + readonly templateId = 'default'; + renderTemplate(container: HTMLElement): HTMLElement { + return container; + } + renderElement(element: ITreeNode, index: number, templateData: HTMLElement): void { + templateData.textContent = element.element.id; + } + disposeTemplate(templateData: HTMLElement): void { + // noop + } + }; + + const getChildrenCalls: string[] = []; + const dataSource = new class implements IAsyncDataSource { + hasChildren(element: Element): boolean { + return !!element.children && element.children.length > 0; + } + getChildren(element: Element): Promise { + getChildrenCalls.push(element.id); + return Promise.resolve(element.children || []); + } + }; + + const identityProvider = new class implements IIdentityProvider { + getId(element: Element) { + return element.id; + } + }; + + const root: Element = { + id: 'root', + children: [{ + id: 'a' + }] + }; + + const _: (id: string) => Element = find.bind(null, root.children); + + const tree = new AsyncDataTree(container, delegate, [renderer], dataSource, { identityProvider }); + tree.layout(200); + + await tree.setInput(root); + assert.deepStrictEqual(getChildrenCalls, ['root']); + + let twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement; + assert(!hasClass(twistie, 'collapsible')); + assert(!hasClass(twistie, 'collapsed')); + assert(tree.getNode().children[0].collapsed); + + _('a').children = [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }]; + await tree.updateChildren(root); + + assert.deepStrictEqual(getChildrenCalls, ['root', 'root']); + twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement; + assert(hasClass(twistie, 'collapsible')); + assert(hasClass(twistie, 'collapsed')); + assert(tree.getNode().children[0].collapsed); + + _('a').children = []; + await tree.updateChildren(root); + + assert.deepStrictEqual(getChildrenCalls, ['root', 'root', 'root']); + twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement; + assert(!hasClass(twistie, 'collapsible')); + assert(!hasClass(twistie, 'collapsed')); + assert(tree.getNode().children[0].collapsed); + + _('a').children = [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }]; + await tree.updateChildren(root); + + assert.deepStrictEqual(getChildrenCalls, ['root', 'root', 'root', 'root']); + twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement; + assert(hasClass(twistie, 'collapsible')); + assert(hasClass(twistie, 'collapsed')); + assert(tree.getNode().children[0].collapsed); + }); + + test('issue #67722 - once resolved, refreshed collapsed nodes should only get children when expanded', async () => { + const container = document.createElement('div'); + container.style.width = '200px'; + container.style.height = '200px'; + + const delegate = new class implements IListVirtualDelegate { + getHeight() { return 20; } + getTemplateId(element: Element): string { return 'default'; } + }; + + const renderer = new class implements ITreeRenderer { + readonly templateId = 'default'; + renderTemplate(container: HTMLElement): HTMLElement { + return container; + } + renderElement(element: ITreeNode, index: number, templateData: HTMLElement): void { + templateData.textContent = element.element.id; + } + disposeTemplate(templateData: HTMLElement): void { + // noop + } + }; + + const getChildrenCalls: string[] = []; + const dataSource = new class implements IAsyncDataSource { + hasChildren(element: Element): boolean { + return !!element.children && element.children.length > 0; + } + getChildren(element: Element): Promise { + getChildrenCalls.push(element.id); + return Promise.resolve(element.children || []); + } + }; + + const identityProvider = new class implements IIdentityProvider { + getId(element: Element) { + return element.id; + } + }; + + const root: Element = { + id: 'root', + children: [{ + id: 'a', children: [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }] + }] + }; + + const _: (id: string) => Element = find.bind(null, root.children); + + const tree = new AsyncDataTree(container, delegate, [renderer], dataSource, { identityProvider }); + tree.layout(200); + + await tree.setInput(root); + assert(tree.getNode(_('a')).collapsed); + assert.deepStrictEqual(getChildrenCalls, ['root']); + + await tree.expand(_('a')); + assert(!tree.getNode(_('a')).collapsed); + assert.deepStrictEqual(getChildrenCalls, ['root', 'a']); + + tree.collapse(_('a')); + assert(tree.getNode(_('a')).collapsed); + assert.deepStrictEqual(getChildrenCalls, ['root', 'a']); + + await tree.updateChildren(); + assert(tree.getNode(_('a')).collapsed); + assert.deepStrictEqual(getChildrenCalls, ['root', 'a', 'root'], 'a should not be refreshed, since it\' collapsed'); + }); + + test('resolved collapsed nodes which lose children should lose twistie as well', async () => { + const container = document.createElement('div'); + container.style.width = '200px'; + container.style.height = '200px'; + + const delegate = new class implements IListVirtualDelegate { + getHeight() { return 20; } + getTemplateId(element: Element): string { return 'default'; } + }; + + const renderer = new class implements ITreeRenderer { + readonly templateId = 'default'; + renderTemplate(container: HTMLElement): HTMLElement { + return container; + } + renderElement(element: ITreeNode, index: number, templateData: HTMLElement): void { + templateData.textContent = element.element.id; + } + disposeTemplate(templateData: HTMLElement): void { + // noop + } + }; + + const dataSource = new class implements IAsyncDataSource { + hasChildren(element: Element): boolean { + return !!element.children && element.children.length > 0; + } + getChildren(element: Element): Promise { + return Promise.resolve(element.children || []); + } + }; + + const identityProvider = new class implements IIdentityProvider { + getId(element: Element) { + return element.id; + } + }; + + const root: Element = { + id: 'root', + children: [{ + id: 'a', children: [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }] + }] + }; + + const _: (id: string) => Element = find.bind(null, root.children); + + const tree = new AsyncDataTree(container, delegate, [renderer], dataSource, { identityProvider }); + tree.layout(200); + + await tree.setInput(root); + await tree.expand(_('a')); + + let twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement; + assert(hasClass(twistie, 'collapsible')); + assert(!hasClass(twistie, 'collapsed')); + assert(!tree.getNode(_('a')).collapsed); + + tree.collapse(_('a')); + _('a').children = []; + await tree.updateChildren(root); + + twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement; + assert(!hasClass(twistie, 'collapsible')); + assert(!hasClass(twistie, 'collapsed')); + assert(tree.getNode(_('a')).collapsed); + }); + + test('support default collapse state per element', async () => { + const container = document.createElement('div'); + container.style.width = '200px'; + container.style.height = '200px'; + + const delegate = new class implements IListVirtualDelegate { + getHeight() { return 20; } + getTemplateId(element: Element): string { return 'default'; } + }; + + const renderer = new class implements ITreeRenderer { + readonly templateId = 'default'; + renderTemplate(container: HTMLElement): HTMLElement { + return container; + } + renderElement(element: ITreeNode, index: number, templateData: HTMLElement): void { + templateData.textContent = element.element.id; + } + disposeTemplate(templateData: HTMLElement): void { + // noop + } + }; + + const getChildrenCalls: string[] = []; + const dataSource = new class implements IAsyncDataSource { + hasChildren(element: Element): boolean { + return !!element.children && element.children.length > 0; + } + getChildren(element: Element): Promise { + getChildrenCalls.push(element.id); + return Promise.resolve(element.children || []); + } + }; + + const root: Element = { + id: 'root', + children: [{ + id: 'a', children: [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }] + }] + }; + + const _: (id: string) => Element = find.bind(null, root.children); + + const tree = new AsyncDataTree(container, delegate, [renderer], dataSource, { + collapseByDefault: el => el.id !== 'a' + }); + tree.layout(200); + + await tree.setInput(root); + assert(!tree.getNode(_('a')).collapsed); + assert.deepStrictEqual(getChildrenCalls, ['root', 'a']); + }); }); \ No newline at end of file diff --git a/src/vs/base/test/browser/ui/tree/compressedObjectTreeModel.test.ts b/src/vs/base/test/browser/ui/tree/compressedObjectTreeModel.test.ts new file mode 100644 index 00000000000..4d03b49a0a8 --- /dev/null +++ b/src/vs/base/test/browser/ui/tree/compressedObjectTreeModel.test.ts @@ -0,0 +1,430 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { compress, ICompressedTreeElement, ICompressedTreeNode, decompress, CompressedTreeModel } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; +import { Iterator } from 'vs/base/common/iterator'; +import { ITreeNode } from 'vs/base/browser/ui/tree/tree'; +import { ISpliceable } from 'vs/base/common/sequence'; + +interface IResolvedCompressedTreeElement extends ICompressedTreeElement { + readonly element: T; + readonly children?: ICompressedTreeElement[]; +} + +function resolve(treeElement: ICompressedTreeElement): IResolvedCompressedTreeElement { + const result: any = { element: treeElement.element }; + const children = Iterator.collect(Iterator.map(Iterator.from(treeElement.children), resolve)); + + if (treeElement.incompressible) { + result.incompressible = true; + } + + if (children.length > 0) { + result.children = children; + } + + return result; +} + +suite('CompressedObjectTree', function () { + + suite('compress & decompress', function () { + + test('small', function () { + const decompressed: ICompressedTreeElement = { element: 1 }; + const compressed: IResolvedCompressedTreeElement> = + { element: { elements: [1], incompressible: false } }; + + assert.deepEqual(resolve(compress(decompressed)), compressed); + assert.deepEqual(resolve(decompress(compressed)), decompressed); + }); + + test('no compression', function () { + const decompressed: ICompressedTreeElement = { + element: 1, children: [ + { element: 11 }, + { element: 12 }, + { element: 13 } + ] + }; + + const compressed: IResolvedCompressedTreeElement> = { + element: { elements: [1], incompressible: false }, + children: [ + { element: { elements: [11], incompressible: false } }, + { element: { elements: [12], incompressible: false } }, + { element: { elements: [13], incompressible: false } } + ] + }; + + assert.deepEqual(resolve(compress(decompressed)), compressed); + assert.deepEqual(resolve(decompress(compressed)), decompressed); + }); + + test('single hierarchy', function () { + const decompressed: ICompressedTreeElement = { + element: 1, children: [ + { + element: 11, children: [ + { + element: 111, children: [ + { element: 1111 } + ] + } + ] + } + ] + }; + + const compressed: IResolvedCompressedTreeElement> = { + element: { elements: [1, 11, 111, 1111], incompressible: false } + }; + + assert.deepEqual(resolve(compress(decompressed)), compressed); + assert.deepEqual(resolve(decompress(compressed)), decompressed); + }); + + test('deep compression', function () { + const decompressed: ICompressedTreeElement = { + element: 1, children: [ + { + element: 11, children: [ + { + element: 111, children: [ + { element: 1111 }, + { element: 1112 }, + { element: 1113 }, + { element: 1114 }, + ] + } + ] + } + ] + }; + + const compressed: IResolvedCompressedTreeElement> = { + element: { elements: [1, 11, 111], incompressible: false }, + children: [ + { element: { elements: [1111], incompressible: false } }, + { element: { elements: [1112], incompressible: false } }, + { element: { elements: [1113], incompressible: false } }, + { element: { elements: [1114], incompressible: false } }, + ] + }; + + assert.deepEqual(resolve(compress(decompressed)), compressed); + assert.deepEqual(resolve(decompress(compressed)), decompressed); + }); + + test('double deep compression', function () { + const decompressed: ICompressedTreeElement = { + element: 1, children: [ + { + element: 11, children: [ + { + element: 111, children: [ + { element: 1112 }, + { element: 1113 }, + ] + } + ] + }, + { + element: 12, children: [ + { + element: 121, children: [ + { element: 1212 }, + { element: 1213 }, + ] + } + ] + } + ] + }; + + const compressed: IResolvedCompressedTreeElement> = { + element: { elements: [1], incompressible: false }, + children: [ + { + element: { elements: [11, 111], incompressible: false }, + children: [ + { element: { elements: [1112], incompressible: false } }, + { element: { elements: [1113], incompressible: false } }, + ] + }, + { + element: { elements: [12, 121], incompressible: false }, + children: [ + { element: { elements: [1212], incompressible: false } }, + { element: { elements: [1213], incompressible: false } }, + ] + } + ] + }; + + assert.deepEqual(resolve(compress(decompressed)), compressed); + assert.deepEqual(resolve(decompress(compressed)), decompressed); + }); + + test('incompressible leaf', function () { + const decompressed: ICompressedTreeElement = { + element: 1, children: [ + { + element: 11, children: [ + { + element: 111, children: [ + { element: 1111, incompressible: true } + ] + } + ] + } + ] + }; + + const compressed: IResolvedCompressedTreeElement> = { + element: { elements: [1, 11, 111], incompressible: false }, + children: [ + { element: { elements: [1111], incompressible: true } } + ] + }; + + assert.deepEqual(resolve(compress(decompressed)), compressed); + assert.deepEqual(resolve(decompress(compressed)), decompressed); + }); + + test('incompressible branch', function () { + const decompressed: ICompressedTreeElement = { + element: 1, children: [ + { + element: 11, children: [ + { + element: 111, incompressible: true, children: [ + { element: 1111 } + ] + } + ] + } + ] + }; + + const compressed: IResolvedCompressedTreeElement> = { + element: { elements: [1, 11], incompressible: false }, + children: [ + { element: { elements: [111, 1111], incompressible: true } } + ] + }; + + assert.deepEqual(resolve(compress(decompressed)), compressed); + assert.deepEqual(resolve(decompress(compressed)), decompressed); + }); + + test('incompressible chain', function () { + const decompressed: ICompressedTreeElement = { + element: 1, children: [ + { + element: 11, children: [ + { + element: 111, incompressible: true, children: [ + { element: 1111, incompressible: true } + ] + } + ] + } + ] + }; + + const compressed: IResolvedCompressedTreeElement> = { + element: { elements: [1, 11], incompressible: false }, + children: [ + { + element: { elements: [111], incompressible: true }, + children: [ + { element: { elements: [1111], incompressible: true } } + ] + } + ] + }; + + assert.deepEqual(resolve(compress(decompressed)), compressed); + assert.deepEqual(resolve(decompress(compressed)), decompressed); + }); + + test('incompressible tree', function () { + const decompressed: ICompressedTreeElement = { + element: 1, children: [ + { + element: 11, incompressible: true, children: [ + { + element: 111, incompressible: true, children: [ + { element: 1111, incompressible: true } + ] + } + ] + } + ] + }; + + const compressed: IResolvedCompressedTreeElement> = { + element: { elements: [1], incompressible: false }, + children: [ + { + element: { elements: [11], incompressible: true }, + children: [ + { + element: { elements: [111], incompressible: true }, + children: [ + { element: { elements: [1111], incompressible: true } } + ] + } + ] + } + ] + }; + + assert.deepEqual(resolve(compress(decompressed)), compressed); + assert.deepEqual(resolve(decompress(compressed)), decompressed); + }); + }); + + function toSpliceable(arr: T[]): ISpliceable { + return { + splice(start: number, deleteCount: number, elements: T[]): void { + arr.splice(start, deleteCount, ...elements); + } + }; + } + + function toArray(list: ITreeNode>[]): T[][] { + return list.map(i => i.element.elements); + } + + suite('CompressedObjectTreeModel', function () { + + test('ctor', () => { + const list: ITreeNode>[] = []; + const model = new CompressedTreeModel(toSpliceable(list)); + assert(model); + assert.equal(list.length, 0); + assert.equal(model.size, 0); + }); + + test('flat', () => { + const list: ITreeNode>[] = []; + const model = new CompressedTreeModel(toSpliceable(list)); + + model.setChildren(null, Iterator.fromArray([ + { element: 0 }, + { element: 1 }, + { element: 2 } + ])); + + assert.deepEqual(toArray(list), [[0], [1], [2]]); + assert.equal(model.size, 3); + + model.setChildren(null, Iterator.fromArray([ + { element: 3 }, + { element: 4 }, + { element: 5 }, + ])); + + assert.deepEqual(toArray(list), [[3], [4], [5]]); + assert.equal(model.size, 3); + + model.setChildren(null, Iterator.empty()); + assert.deepEqual(toArray(list), []); + assert.equal(model.size, 0); + }); + + test('nested', () => { + const list: ITreeNode>[] = []; + const model = new CompressedTreeModel(toSpliceable(list)); + + model.setChildren(null, Iterator.fromArray([ + { + element: 0, children: Iterator.fromArray([ + { element: 10 }, + { element: 11 }, + { element: 12 }, + ]) + }, + { element: 1 }, + { element: 2 } + ])); + + assert.deepEqual(toArray(list), [[0], [10], [11], [12], [1], [2]]); + assert.equal(model.size, 6); + + model.setChildren(12, Iterator.fromArray([ + { element: 120 }, + { element: 121 } + ])); + + assert.deepEqual(toArray(list), [[0], [10], [11], [12], [120], [121], [1], [2]]); + assert.equal(model.size, 8); + + model.setChildren(0, Iterator.empty()); + assert.deepEqual(toArray(list), [[0], [1], [2]]); + assert.equal(model.size, 3); + + model.setChildren(null, Iterator.empty()); + assert.deepEqual(toArray(list), []); + assert.equal(model.size, 0); + }); + + test('compressed', () => { + const list: ITreeNode>[] = []; + const model = new CompressedTreeModel(toSpliceable(list)); + + model.setChildren(null, Iterator.fromArray([ + { + element: 1, children: Iterator.fromArray([{ + element: 11, children: Iterator.fromArray([{ + element: 111, children: Iterator.fromArray([ + { element: 1111 }, + { element: 1112 }, + { element: 1113 }, + ]) + }]) + }]) + } + ])); + + assert.deepEqual(toArray(list), [[1, 11, 111], [1111], [1112], [1113]]); + assert.equal(model.size, 6); + + model.setChildren(11, Iterator.fromArray([ + { element: 111 }, + { element: 112 }, + { element: 113 }, + ])); + + assert.deepEqual(toArray(list), [[1, 11], [111], [112], [113]]); + assert.equal(model.size, 5); + + model.setChildren(113, Iterator.fromArray([ + { element: 1131 } + ])); + + assert.deepEqual(toArray(list), [[1, 11], [111], [112], [113, 1131]]); + assert.equal(model.size, 6); + + model.setChildren(1131, Iterator.fromArray([ + { element: 1132 } + ])); + + assert.deepEqual(toArray(list), [[1, 11], [111], [112], [113, 1131, 1132]]); + assert.equal(model.size, 7); + + model.setChildren(1131, Iterator.fromArray([ + { element: 1132 }, + { element: 1133 }, + ])); + + assert.deepEqual(toArray(list), [[1, 11], [111], [112], [113, 1131], [1132], [1133]]); + assert.equal(model.size, 8); + }); + }); +}); \ No newline at end of file diff --git a/src/vs/base/test/browser/ui/tree/objectTree.test.ts b/src/vs/base/test/browser/ui/tree/objectTree.test.ts index 3424665b111..46e03f8884d 100644 --- a/src/vs/base/test/browser/ui/tree/objectTree.test.ts +++ b/src/vs/base/test/browser/ui/tree/objectTree.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import { ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; -import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list'; import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; import { Iterator } from 'vs/base/common/iterator'; @@ -186,4 +186,42 @@ suite('ObjectTree', function () { assert.equal(navigator.last(), 2); }); }); + + test('traits are preserved according to string identity', function () { + const container = document.createElement('div'); + container.style.width = '200px'; + container.style.height = '200px'; + + const delegate = new class implements IListVirtualDelegate { + getHeight() { return 20; } + getTemplateId(): string { return 'default'; } + }; + + const renderer = new class implements ITreeRenderer { + readonly templateId = 'default'; + renderTemplate(container: HTMLElement): HTMLElement { + return container; + } + renderElement(element: ITreeNode, index: number, templateData: HTMLElement): void { + templateData.textContent = `${element.element}`; + } + disposeTemplate(): void { } + }; + + const identityProvider = new class implements IIdentityProvider { + getId(element: number): { toString(): string; } { + return `${element % 100}`; + } + }; + + const tree = new ObjectTree(container, delegate, [renderer], { identityProvider }); + tree.layout(200); + + tree.setChildren(null, [{ element: 0 }, { element: 1 }, { element: 2 }, { element: 3 }]); + tree.setFocus([1]); + assert.deepStrictEqual(tree.getFocus(), [1]); + + tree.setChildren(null, [{ element: 100 }, { element: 101 }, { element: 102 }, { element: 103 }]); + assert.deepStrictEqual(tree.getFocus(), [101]); + }); }); \ No newline at end of file diff --git a/src/vs/base/test/browser/ui/tree/objectTreeModel.test.ts b/src/vs/base/test/browser/ui/tree/objectTreeModel.test.ts index 3e6a1797b01..6a5ec8713c5 100644 --- a/src/vs/base/test/browser/ui/tree/objectTreeModel.test.ts +++ b/src/vs/base/test/browser/ui/tree/objectTreeModel.test.ts @@ -168,4 +168,77 @@ suite('ObjectTreeModel', function () { model.setChildren(null, data); assert.deepEqual(toArray(list), ['father']); }); + + test('sorter', () => { + let compare: (a: string, b: string) => number = (a, b) => a < b ? -1 : 1; + + const list: ITreeNode[] = []; + const model = new ObjectTreeModel(toSpliceable(list), { sorter: { compare(a, b) { return compare(a, b); } } }); + const data = [ + { element: 'cars', children: [{ element: 'sedan' }, { element: 'convertible' }, { element: 'compact' }] }, + { element: 'airplanes', children: [{ element: 'passenger' }, { element: 'jet' }] }, + { element: 'bicycles', children: [{ element: 'dutch' }, { element: 'mountain' }, { element: 'electric' }] }, + ]; + + model.setChildren(null, data); + assert.deepEqual(toArray(list), ['airplanes', 'jet', 'passenger', 'bicycles', 'dutch', 'electric', 'mountain', 'cars', 'compact', 'convertible', 'sedan']); + }); + + test('resort', () => { + let compare: (a: string, b: string) => number = () => 0; + + const list: ITreeNode[] = []; + const model = new ObjectTreeModel(toSpliceable(list), { sorter: { compare(a, b) { return compare(a, b); } } }); + const data = [ + { element: 'cars', children: [{ element: 'sedan' }, { element: 'convertible' }, { element: 'compact' }] }, + { element: 'airplanes', children: [{ element: 'passenger' }, { element: 'jet' }] }, + { element: 'bicycles', children: [{ element: 'dutch' }, { element: 'mountain' }, { element: 'electric' }] }, + ]; + + model.setChildren(null, data); + assert.deepEqual(toArray(list), ['cars', 'sedan', 'convertible', 'compact', 'airplanes', 'passenger', 'jet', 'bicycles', 'dutch', 'mountain', 'electric']); + + // lexicographical + compare = (a, b) => a < b ? -1 : 1; + + // non-recursive + model.resort(null, false); + assert.deepEqual(toArray(list), ['airplanes', 'passenger', 'jet', 'bicycles', 'dutch', 'mountain', 'electric', 'cars', 'sedan', 'convertible', 'compact']); + + // recursive + model.resort(); + assert.deepEqual(toArray(list), ['airplanes', 'jet', 'passenger', 'bicycles', 'dutch', 'electric', 'mountain', 'cars', 'compact', 'convertible', 'sedan']); + + // reverse + compare = (a, b) => a < b ? 1 : -1; + + // scoped + model.resort('cars'); + assert.deepEqual(toArray(list), ['airplanes', 'jet', 'passenger', 'bicycles', 'dutch', 'electric', 'mountain', 'cars', 'sedan', 'convertible', 'compact']); + + // recursive + model.resort(); + assert.deepEqual(toArray(list), ['cars', 'sedan', 'convertible', 'compact', 'bicycles', 'mountain', 'electric', 'dutch', 'airplanes', 'passenger', 'jet']); + }); + + test('expandTo', () => { + const list: ITreeNode[] = []; + const model = new ObjectTreeModel(toSpliceable(list), { collapseByDefault: true }); + + model.setChildren(null, [ + { + element: 0, children: [ + { element: 10, children: [{ element: 100, children: [{ element: 1000 }] }] }, + { element: 11 }, + { element: 12 }, + ] + }, + { element: 1 }, + { element: 2 } + ]); + + assert.deepEqual(toArray(list), [0, 1, 2]); + model.expandTo(1000); + assert.deepEqual(toArray(list), [0, 10, 100, 1000, 11, 12, 1, 2]); + }); }); \ No newline at end of file diff --git a/src/vs/base/test/common/arrays.test.ts b/src/vs/base/test/common/arrays.test.ts index b999d91e2c4..4c0fe3e3e17 100644 --- a/src/vs/base/test/common/arrays.test.ts +++ b/src/vs/base/test/common/arrays.test.ts @@ -32,8 +32,16 @@ suite('Arrays', () => { }); test('stableSort', () => { + function fill(num: number, valueFn: () => T, arr: T[] = []): T[] { + for (let i = 0; i < num; i++) { + arr[i] = valueFn(); + } + + return arr; + } + let counter = 0; - let data = arrays.fill(10000, () => ({ n: 1, m: counter++ })); + let data = fill(10000, () => ({ n: 1, m: counter++ })); arrays.mergeSort(data, (a, b) => a.n - b.n); @@ -262,7 +270,7 @@ suite('Arrays', () => { } test('coalesce', () => { - let a: Array = arrays.coalesce([null, 1, null, 2, 3]); + let a: Array = arrays.coalesce([null, 1, null, 2, 3]); assert.equal(a.length, 3); assert.equal(a[0], 1); assert.equal(a[1], 2); @@ -298,7 +306,7 @@ suite('Arrays', () => { }); test('coalesce - inplace', function () { - let a: Array = [null, 1, null, 2, 3]; + let a: Array = [null, 1, null, 2, 3]; arrays.coalesceInPlace(a); assert.equal(a.length, 3); assert.equal(a[0], 1); diff --git a/src/vs/base/test/common/async.test.ts b/src/vs/base/test/common/async.test.ts index b22a84ac046..586c0fa8a7f 100644 --- a/src/vs/base/test/common/async.test.ts +++ b/src/vs/base/test/common/async.test.ts @@ -531,4 +531,30 @@ suite('Async', () => { assert.notEqual(r1Queue, r1Queue2); // previous one got disposed after finishing }); }); + + test('retry - success case', async () => { + let counter = 0; + + const res = await async.retry(() => { + counter++; + if (counter < 2) { + return Promise.reject(new Error('fail')); + } + + return Promise.resolve(true); + }, 10, 3); + + assert.equal(res, true); + }); + + test('retry - error case', async () => { + let expectedError = new Error('fail'); + try { + await async.retry(() => { + return Promise.reject(expectedError); + }, 10, 3); + } catch (error) { + assert.equal(error, error); + } + }); }); diff --git a/src/vs/base/test/common/cancellation.test.ts b/src/vs/base/test/common/cancellation.test.ts index 74102fafc07..536b2e21139 100644 --- a/src/vs/base/test/common/cancellation.test.ts +++ b/src/vs/base/test/common/cancellation.test.ts @@ -94,4 +94,19 @@ suite('CancellationToken', function () { source.cancel(); assert.equal(count, 0); }); + + test('parent cancels child', function () { + + let parent = new CancellationTokenSource(); + let child = new CancellationTokenSource(parent.token); + + let count = 0; + child.token.onCancellationRequested(() => count += 1); + + parent.cancel(); + + assert.equal(count, 1); + assert.equal(child.token.isCancellationRequested, true); + assert.equal(parent.token.isCancellationRequested, true); + }); }); diff --git a/src/vs/base/test/common/decorators.test.ts b/src/vs/base/test/common/decorators.test.ts index aaabb2b5094..05a58c318c0 100644 --- a/src/vs/base/test/common/decorators.test.ts +++ b/src/vs/base/test/common/decorators.test.ts @@ -119,7 +119,7 @@ suite('Decorators', () => { assert.equal(foo.answer, 42); try { - foo['$memoize$answer'] = 1337; + (foo as any)['$memoize$answer'] = 1337; assert(false); } catch (e) { assert.equal(foo.answer, 42); diff --git a/src/vs/base/test/common/event.test.ts b/src/vs/base/test/common/event.test.ts index a08f0aa538c..039743bbb39 100644 --- a/src/vs/base/test/common/event.test.ts +++ b/src/vs/base/test/common/event.test.ts @@ -3,8 +3,8 @@ * 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, AsyncEmitter, IWaitUntil } from 'vs/base/common/event'; -import { IDisposable } from 'vs/base/common/lifecycle'; +import { Event, Emitter, EventBufferer, EventMultiplexer, AsyncEmitter, IWaitUntil, 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'; @@ -73,6 +73,27 @@ suite('Event', function () { while (bucket.length) { bucket.pop()!.dispose(); } + doc.setText('boo'); + + // noop + subscription.dispose(); + + doc.setText('boo'); + assert.equal(counter.count, 2); + }); + + test('Emitter, store', function () { + + let bucket = new DisposableStore(); + let doc = new Samples.Document3(); + let subscription = doc.onDidChange(counter.onEvent, counter, bucket); + + doc.setText('far'); + doc.setText('boo'); + + // unhook listener + bucket.clear(); + doc.setText('boo'); // noop subscription.dispose(); @@ -331,6 +352,133 @@ suite('AsyncEmitter', function () { }); }); +suite('PausableEmitter', function () { + + test('basic', function () { + const data: number[] = []; + const emitter = new PauseableEmitter(); + + emitter.event(e => data.push(e)); + emitter.fire(1); + emitter.fire(2); + + assert.deepEqual(data, [1, 2]); + }); + + test('pause/resume - no merge', function () { + const data: number[] = []; + const emitter = new PauseableEmitter(); + + emitter.event(e => data.push(e)); + emitter.fire(1); + emitter.fire(2); + assert.deepEqual(data, [1, 2]); + + emitter.pause(); + emitter.fire(3); + emitter.fire(4); + assert.deepEqual(data, [1, 2]); + + emitter.resume(); + assert.deepEqual(data, [1, 2, 3, 4]); + emitter.fire(5); + assert.deepEqual(data, [1, 2, 3, 4, 5]); + }); + + test('pause/resume - merge', function () { + const data: number[] = []; + const emitter = new PauseableEmitter({ merge: (a) => a.reduce((p, c) => p + c, 0) }); + + emitter.event(e => data.push(e)); + emitter.fire(1); + emitter.fire(2); + assert.deepEqual(data, [1, 2]); + + emitter.pause(); + emitter.fire(3); + emitter.fire(4); + assert.deepEqual(data, [1, 2]); + + emitter.resume(); + assert.deepEqual(data, [1, 2, 7]); + + emitter.fire(5); + assert.deepEqual(data, [1, 2, 7, 5]); + }); + + test('double pause/resume', function () { + const data: number[] = []; + const emitter = new PauseableEmitter(); + + emitter.event(e => data.push(e)); + emitter.fire(1); + emitter.fire(2); + assert.deepEqual(data, [1, 2]); + + emitter.pause(); + emitter.pause(); + emitter.fire(3); + emitter.fire(4); + assert.deepEqual(data, [1, 2]); + + emitter.resume(); + assert.deepEqual(data, [1, 2]); + + emitter.resume(); + assert.deepEqual(data, [1, 2, 3, 4]); + + emitter.resume(); + assert.deepEqual(data, [1, 2, 3, 4]); + }); + + test('resume, no pause', function () { + const data: number[] = []; + const emitter = new PauseableEmitter(); + + emitter.event(e => data.push(e)); + emitter.fire(1); + emitter.fire(2); + assert.deepEqual(data, [1, 2]); + + emitter.resume(); + emitter.fire(3); + assert.deepEqual(data, [1, 2, 3]); + }); + + test('nested pause', function () { + const data: number[] = []; + const emitter = new PauseableEmitter(); + + let once = true; + emitter.event(e => { + data.push(e); + + if (once) { + emitter.pause(); + once = false; + } + }); + emitter.event(e => { + data.push(e); + }); + + emitter.pause(); + emitter.fire(1); + emitter.fire(2); + assert.deepEqual(data, []); + + emitter.resume(); + assert.deepEqual(data, [1, 1]); // paused after first event + + emitter.resume(); + assert.deepEqual(data, [1, 1, 2, 2]); // remaing event delivered + + emitter.fire(3); + assert.deepEqual(data, [1, 1, 2, 2, 3, 3]); + + }); +}); + suite('Event utils', () => { suite('EventBufferer', () => { @@ -518,67 +666,6 @@ suite('Event utils', () => { }); }); - suite('echo', () => { - - test('should echo events', () => { - const result: number[] = []; - const emitter = new Emitter(); - const event = emitter.event; - const echoEvent = Event.echo(event); - - emitter.fire(1); - emitter.fire(2); - emitter.fire(3); - assert.deepEqual(result, []); - - const listener = echoEvent(num => result.push(num)); - assert.deepEqual(result, [1, 2, 3]); - - emitter.fire(4); - assert.deepEqual(result, [1, 2, 3, 4]); - - listener.dispose(); - emitter.fire(5); - assert.deepEqual(result, [1, 2, 3, 4]); - }); - - test('should echo events for every listener', () => { - const result1: number[] = []; - const result2: number[] = []; - const emitter = new Emitter(); - const event = emitter.event; - const echoEvent = Event.echo(event); - - emitter.fire(1); - emitter.fire(2); - emitter.fire(3); - assert.deepEqual(result1, []); - assert.deepEqual(result2, []); - - const listener1 = echoEvent(num => result1.push(num)); - assert.deepEqual(result1, [1, 2, 3]); - assert.deepEqual(result2, []); - - emitter.fire(4); - assert.deepEqual(result1, [1, 2, 3, 4]); - assert.deepEqual(result2, []); - - const listener2 = echoEvent(num => result2.push(num)); - assert.deepEqual(result1, [1, 2, 3, 4]); - assert.deepEqual(result2, [1, 2, 3, 4]); - - emitter.fire(5); - assert.deepEqual(result1, [1, 2, 3, 4, 5]); - assert.deepEqual(result2, [1, 2, 3, 4, 5]); - - listener1.dispose(); - listener2.dispose(); - emitter.fire(6); - assert.deepEqual(result1, [1, 2, 3, 4, 5]); - assert.deepEqual(result2, [1, 2, 3, 4, 5]); - }); - }); - suite('EventMultiplexer', () => { test('works', () => { @@ -777,4 +864,5 @@ suite('Event utils', () => { listener.dispose(); }); + }); diff --git a/src/vs/base/test/common/extpath.test.ts b/src/vs/base/test/common/extpath.test.ts new file mode 100644 index 00000000000..da6da32873f --- /dev/null +++ b/src/vs/base/test/common/extpath.test.ts @@ -0,0 +1,117 @@ +/*--------------------------------------------------------------------------------------------- + * 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 extpath from 'vs/base/common/extpath'; +import * as platform from 'vs/base/common/platform'; + +suite('Paths', () => { + + test('toForwardSlashes', () => { + assert.equal(extpath.toSlashes('\\\\server\\share\\some\\path'), '//server/share/some/path'); + assert.equal(extpath.toSlashes('c:\\test'), 'c:/test'); + assert.equal(extpath.toSlashes('foo\\bar'), 'foo/bar'); + assert.equal(extpath.toSlashes('/user/far'), '/user/far'); + }); + + test('getRoot', () => { + assert.equal(extpath.getRoot('/user/far'), '/'); + assert.equal(extpath.getRoot('\\\\server\\share\\some\\path'), '//server/share/'); + assert.equal(extpath.getRoot('//server/share/some/path'), '//server/share/'); + assert.equal(extpath.getRoot('//server/share'), '/'); + assert.equal(extpath.getRoot('//server'), '/'); + assert.equal(extpath.getRoot('//server//'), '/'); + assert.equal(extpath.getRoot('c:/user/far'), 'c:/'); + assert.equal(extpath.getRoot('c:user/far'), 'c:'); + assert.equal(extpath.getRoot('http://www'), ''); + assert.equal(extpath.getRoot('http://www/'), 'http://www/'); + assert.equal(extpath.getRoot('file:///foo'), 'file:///'); + assert.equal(extpath.getRoot('file://foo'), ''); + + }); + + test('isUNC', () => { + if (platform.isWindows) { + assert.ok(!extpath.isUNC('foo')); + assert.ok(!extpath.isUNC('/foo')); + assert.ok(!extpath.isUNC('\\foo')); + assert.ok(!extpath.isUNC('\\\\foo')); + assert.ok(extpath.isUNC('\\\\a\\b')); + assert.ok(!extpath.isUNC('//a/b')); + assert.ok(extpath.isUNC('\\\\server\\share')); + assert.ok(extpath.isUNC('\\\\server\\share\\')); + assert.ok(extpath.isUNC('\\\\server\\share\\path')); + } + }); + + test('isValidBasename', () => { + assert.ok(!extpath.isValidBasename(null)); + assert.ok(!extpath.isValidBasename('')); + assert.ok(extpath.isValidBasename('test.txt')); + assert.ok(!extpath.isValidBasename('/test.txt')); + assert.ok(!extpath.isValidBasename('\\test.txt')); + + if (platform.isWindows) { + assert.ok(!extpath.isValidBasename('aux')); + assert.ok(!extpath.isValidBasename('Aux')); + assert.ok(!extpath.isValidBasename('LPT0')); + assert.ok(!extpath.isValidBasename('test.txt.')); + assert.ok(!extpath.isValidBasename('test.txt..')); + assert.ok(!extpath.isValidBasename('test.txt ')); + assert.ok(!extpath.isValidBasename('test.txt\t')); + assert.ok(!extpath.isValidBasename('tes:t.txt')); + assert.ok(!extpath.isValidBasename('tes"t.txt')); + } + }); + + test('sanitizeFilePath', () => { + if (platform.isWindows) { + assert.equal(extpath.sanitizeFilePath('.', 'C:\\the\\cwd'), 'C:\\the\\cwd'); + assert.equal(extpath.sanitizeFilePath('', 'C:\\the\\cwd'), 'C:\\the\\cwd'); + + assert.equal(extpath.sanitizeFilePath('C:', 'C:\\the\\cwd'), 'C:\\'); + assert.equal(extpath.sanitizeFilePath('C:\\', 'C:\\the\\cwd'), 'C:\\'); + assert.equal(extpath.sanitizeFilePath('C:\\\\', 'C:\\the\\cwd'), 'C:\\'); + + assert.equal(extpath.sanitizeFilePath('C:\\folder\\my.txt', 'C:\\the\\cwd'), 'C:\\folder\\my.txt'); + assert.equal(extpath.sanitizeFilePath('C:\\folder\\my', 'C:\\the\\cwd'), 'C:\\folder\\my'); + assert.equal(extpath.sanitizeFilePath('C:\\folder\\..\\my', 'C:\\the\\cwd'), 'C:\\my'); + assert.equal(extpath.sanitizeFilePath('C:\\folder\\my\\', 'C:\\the\\cwd'), 'C:\\folder\\my'); + assert.equal(extpath.sanitizeFilePath('C:\\folder\\my\\\\\\', 'C:\\the\\cwd'), 'C:\\folder\\my'); + + assert.equal(extpath.sanitizeFilePath('my.txt', 'C:\\the\\cwd'), 'C:\\the\\cwd\\my.txt'); + assert.equal(extpath.sanitizeFilePath('my.txt\\', 'C:\\the\\cwd'), 'C:\\the\\cwd\\my.txt'); + + assert.equal(extpath.sanitizeFilePath('\\\\localhost\\folder\\my', 'C:\\the\\cwd'), '\\\\localhost\\folder\\my'); + assert.equal(extpath.sanitizeFilePath('\\\\localhost\\folder\\my\\', 'C:\\the\\cwd'), '\\\\localhost\\folder\\my'); + } else { + assert.equal(extpath.sanitizeFilePath('.', '/the/cwd'), '/the/cwd'); + assert.equal(extpath.sanitizeFilePath('', '/the/cwd'), '/the/cwd'); + assert.equal(extpath.sanitizeFilePath('/', '/the/cwd'), '/'); + + assert.equal(extpath.sanitizeFilePath('/folder/my.txt', '/the/cwd'), '/folder/my.txt'); + assert.equal(extpath.sanitizeFilePath('/folder/my', '/the/cwd'), '/folder/my'); + assert.equal(extpath.sanitizeFilePath('/folder/../my', '/the/cwd'), '/my'); + assert.equal(extpath.sanitizeFilePath('/folder/my/', '/the/cwd'), '/folder/my'); + assert.equal(extpath.sanitizeFilePath('/folder/my///', '/the/cwd'), '/folder/my'); + + assert.equal(extpath.sanitizeFilePath('my.txt', '/the/cwd'), '/the/cwd/my.txt'); + assert.equal(extpath.sanitizeFilePath('my.txt/', '/the/cwd'), '/the/cwd/my.txt'); + } + }); + + test('isRoot', () => { + if (platform.isWindows) { + assert.ok(extpath.isRootOrDriveLetter('c:')); + assert.ok(extpath.isRootOrDriveLetter('D:')); + assert.ok(extpath.isRootOrDriveLetter('D:/')); + assert.ok(extpath.isRootOrDriveLetter('D:\\')); + assert.ok(!extpath.isRootOrDriveLetter('D:\\path')); + assert.ok(!extpath.isRootOrDriveLetter('D:/path')); + } else { + assert.ok(extpath.isRootOrDriveLetter('/')); + assert.ok(!extpath.isRootOrDriveLetter('/path')); + } + }); +}); diff --git a/src/vs/base/test/common/filters.test.ts b/src/vs/base/test/common/filters.test.ts index d8f84b0aced..25cc50d5780 100644 --- a/src/vs/base/test/common/filters.test.ts +++ b/src/vs/base/test/common/filters.test.ts @@ -3,18 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { IFilter, or, matchesPrefix, matchesStrictPrefix, matchesCamelCase, matchesSubString, matchesContiguousSubString, matchesWords, fuzzyScore, IMatch, fuzzyScoreGraceful, fuzzyScoreGracefulAggressive, FuzzyScorer } from 'vs/base/common/filters'; +import { IFilter, or, matchesPrefix, matchesStrictPrefix, matchesCamelCase, matchesSubString, matchesContiguousSubString, matchesWords, fuzzyScore, IMatch, fuzzyScoreGraceful, fuzzyScoreGracefulAggressive, FuzzyScorer, createMatches } from 'vs/base/common/filters'; function filterOk(filter: IFilter, word: string, wordToMatchAgainst: string, highlights?: { start: number; end: number; }[]) { let r = filter(word, wordToMatchAgainst); - assert(r); + assert(r, `${word} didn't match ${wordToMatchAgainst}`); if (highlights) { assert.deepEqual(r, highlights); } } -function filterNotOk(filter: IFilter, word: string, suggestion: string) { - assert(!filter(word, suggestion)); +function filterNotOk(filter: IFilter, word: string, wordToMatchAgainst: string) { + assert(!filter(word, wordToMatchAgainst), `${word} matched ${wordToMatchAgainst}`); } suite('Filters', () => { @@ -185,37 +185,54 @@ suite('Filters', () => { assert(matchesWords('Debug Console', 'Open: Debug Console')); filterOk(matchesWords, 'gp', 'Git: Pull', [{ start: 0, end: 1 }, { start: 5, end: 6 }]); - filterOk(matchesWords, 'g p', 'Git: Pull', [{ start: 0, end: 1 }, { start: 4, end: 6 }]); + filterOk(matchesWords, 'g p', 'Git: Pull', [{ start: 0, end: 1 }, { start: 3, end: 4 }, { start: 5, end: 6 }]); filterOk(matchesWords, 'gipu', 'Git: Pull', [{ start: 0, end: 2 }, { start: 5, end: 7 }]); filterOk(matchesWords, 'gp', 'Category: Git: Pull', [{ start: 10, end: 11 }, { start: 15, end: 16 }]); - filterOk(matchesWords, 'g p', 'Category: Git: Pull', [{ start: 10, end: 11 }, { start: 14, end: 16 }]); + filterOk(matchesWords, 'g p', 'Category: Git: Pull', [{ start: 10, end: 11 }, { start: 13, end: 14 }, { start: 15, end: 16 }]); filterOk(matchesWords, 'gipu', 'Category: Git: Pull', [{ start: 10, end: 12 }, { start: 15, end: 17 }]); filterNotOk(matchesWords, 'it', 'Git: Pull'); filterNotOk(matchesWords, 'll', 'Git: Pull'); filterOk(matchesWords, 'git: プル', 'git: プル', [{ start: 0, end: 7 }]); - filterOk(matchesWords, 'git プル', 'git: プル', [{ start: 0, end: 3 }, { start: 4, end: 7 }]); + filterOk(matchesWords, 'git プル', 'git: プル', [{ start: 0, end: 4 }, { start: 5, end: 7 }]); filterOk(matchesWords, 'öäk', 'Öhm: Älles Klar', [{ start: 0, end: 1 }, { start: 5, end: 6 }, { start: 11, end: 12 }]); - assert.ok(matchesWords('gipu', 'Category: Git: Pull', true) === null); - assert.deepEqual(matchesWords('pu', 'Category: Git: Pull', true), [{ start: 15, end: 17 }]); + // assert.ok(matchesWords('gipu', 'Category: Git: Pull', true) === null); + // assert.deepEqual(matchesWords('pu', 'Category: Git: Pull', true), [{ start: 15, end: 17 }]); + + filterOk(matchesWords, 'bar', 'foo-bar'); + filterOk(matchesWords, 'bar test', 'foo-bar test'); + filterOk(matchesWords, 'fbt', 'foo-bar test'); + filterOk(matchesWords, 'bar test', 'foo-bar (test)'); + filterOk(matchesWords, 'foo bar', 'foo (bar)'); + + filterNotOk(matchesWords, 'bar est', 'foo-bar test'); + filterNotOk(matchesWords, 'fo ar', 'foo-bar test'); + filterNotOk(matchesWords, 'for', 'foo-bar test'); + + filterOk(matchesWords, 'foo bar', 'foo-bar'); + filterOk(matchesWords, 'foo bar', '123 foo-bar 456'); + filterOk(matchesWords, 'foo+bar', 'foo-bar'); + filterOk(matchesWords, 'foo-bar', 'foo bar'); + filterOk(matchesWords, 'foo:bar', 'foo:bar'); }); function assertMatches(pattern: string, word: string, decoratedWord: string | undefined, filter: FuzzyScorer, opts: { patternPos?: number, wordPos?: number, firstMatchCanBeWeak?: boolean } = {}) { let r = filter(pattern, pattern.toLowerCase(), opts.patternPos || 0, word, word.toLowerCase(), opts.wordPos || 0, opts.firstMatchCanBeWeak || false); assert.ok(!decoratedWord === !r); if (r) { - let [, matches] = r; + let matches = createMatches(r); let actualWord = ''; - for (let pos = 0; pos < word.length; pos++) { - if (2 ** pos & matches) { - actualWord += '^'; - } - actualWord += word[pos]; + let pos = 0; + for (const match of matches) { + actualWord += word.substring(pos, match.start); + actualWord += '^' + word.substring(match.start, match.end).split('').join('^'); + pos = match.end; } + actualWord += word.substring(pos); assert.equal(actualWord, decoratedWord); } } @@ -449,4 +466,23 @@ suite('Filters', () => { assertMatches('cno', 'co_new', '^c^o_^new', fuzzyScoreGraceful); assertMatches('cno', 'co_new', '^c^o_^new', fuzzyScoreGracefulAggressive); }); + + test('List highlight filter: Not all characters from match are highlighterd #66923', () => { + assertMatches('foo', 'barbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar_foo', 'barbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar_^f^o^o', fuzzyScore); + }); + + test('Autocompletion is matched against truncated filterText to 54 characters #74133', () => { + assertMatches( + 'foo', + 'ffffffffffffffffffffffffffffbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar_foo', + 'ffffffffffffffffffffffffffffbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar_^f^o^o', + fuzzyScore + ); + assertMatches( + 'foo', + 'Gffffffffffffffffffffffffffffbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar_foo', + undefined, + fuzzyScore + ); + }); }); diff --git a/src/vs/base/test/common/iterator.test.ts b/src/vs/base/test/common/iterator.test.ts new file mode 100644 index 00000000000..b7a165c5095 --- /dev/null +++ b/src/vs/base/test/common/iterator.test.ts @@ -0,0 +1,19 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { Iterator } from 'vs/base/common/iterator'; + +suite('Iterator', () => { + test('concat', () => { + const first = Iterator.fromArray([1, 2, 3]); + const second = Iterator.fromArray([4, 5, 6]); + const third = Iterator.fromArray([7, 8, 9]); + const actualIterator = Iterator.concat(first, second, third); + const actual = Iterator.collect(actualIterator); + + assert.deepEqual(actual, [1, 2, 3, 4, 5, 6, 7, 8, 9]); + }); +}); \ No newline at end of file diff --git a/src/vs/base/test/common/keyCodes.test.ts b/src/vs/base/test/common/keyCodes.test.ts index 1a72d1bda6e..f8b2b55a452 100644 --- a/src/vs/base/test/common/keyCodes.test.ts +++ b/src/vs/base/test/common/keyCodes.test.ts @@ -20,35 +20,35 @@ suite('keyCodes', () => { } test(null, 0); - test(new SimpleKeybinding(false, false, false, false, KeyCode.Enter), KeyCode.Enter); - test(new SimpleKeybinding(true, false, false, false, KeyCode.Enter), KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(false, false, true, false, KeyCode.Enter), KeyMod.Alt | KeyCode.Enter); - test(new SimpleKeybinding(true, false, true, false, KeyCode.Enter), KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(false, true, false, false, KeyCode.Enter), KeyMod.Shift | KeyCode.Enter); - test(new SimpleKeybinding(true, true, false, false, KeyCode.Enter), KeyMod.Shift | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(false, true, true, false, KeyCode.Enter), KeyMod.Shift | KeyMod.Alt | KeyCode.Enter); - test(new SimpleKeybinding(true, true, true, false, KeyCode.Enter), KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(false, false, false, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyCode.Enter); - test(new SimpleKeybinding(true, false, false, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(false, false, true, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Enter); - test(new SimpleKeybinding(true, false, true, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(false, true, false, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter); - test(new SimpleKeybinding(true, true, false, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(false, true, true, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.Enter); - test(new SimpleKeybinding(true, true, true, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, false, false, false, KeyCode.Enter).toChord(), KeyCode.Enter); + test(new SimpleKeybinding(true, false, false, false, KeyCode.Enter).toChord(), KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, false, true, false, KeyCode.Enter).toChord(), KeyMod.Alt | KeyCode.Enter); + test(new SimpleKeybinding(true, false, true, false, KeyCode.Enter).toChord(), KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, true, false, false, KeyCode.Enter).toChord(), KeyMod.Shift | KeyCode.Enter); + test(new SimpleKeybinding(true, true, false, false, KeyCode.Enter).toChord(), KeyMod.Shift | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, true, true, false, KeyCode.Enter).toChord(), KeyMod.Shift | KeyMod.Alt | KeyCode.Enter); + test(new SimpleKeybinding(true, true, true, false, KeyCode.Enter).toChord(), KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, false, false, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyCode.Enter); + test(new SimpleKeybinding(true, false, false, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, false, true, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Enter); + test(new SimpleKeybinding(true, false, true, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, true, false, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter); + test(new SimpleKeybinding(true, true, false, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, true, true, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.Enter); + test(new SimpleKeybinding(true, true, true, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); test( - new ChordKeybinding( + new ChordKeybinding([ new SimpleKeybinding(false, false, false, false, KeyCode.Enter), new SimpleKeybinding(false, false, false, false, KeyCode.Tab) - ), + ]), KeyChord(KeyCode.Enter, KeyCode.Tab) ); test( - new ChordKeybinding( + new ChordKeybinding([ new SimpleKeybinding(false, false, false, true, KeyCode.KEY_Y), new SimpleKeybinding(false, false, false, false, KeyCode.KEY_Z) - ), + ]), KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_Y, KeyCode.KEY_Z) ); }); @@ -62,35 +62,35 @@ suite('keyCodes', () => { } test(null, 0); - test(new SimpleKeybinding(false, false, false, false, KeyCode.Enter), KeyCode.Enter); - test(new SimpleKeybinding(false, false, false, true, KeyCode.Enter), KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(false, false, true, false, KeyCode.Enter), KeyMod.Alt | KeyCode.Enter); - test(new SimpleKeybinding(false, false, true, true, KeyCode.Enter), KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(false, true, false, false, KeyCode.Enter), KeyMod.Shift | KeyCode.Enter); - test(new SimpleKeybinding(false, true, false, true, KeyCode.Enter), KeyMod.Shift | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(false, true, true, false, KeyCode.Enter), KeyMod.Shift | KeyMod.Alt | KeyCode.Enter); - test(new SimpleKeybinding(false, true, true, true, KeyCode.Enter), KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(true, false, false, false, KeyCode.Enter), KeyMod.CtrlCmd | KeyCode.Enter); - test(new SimpleKeybinding(true, false, false, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(true, false, true, false, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Enter); - test(new SimpleKeybinding(true, false, true, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(true, true, false, false, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter); - test(new SimpleKeybinding(true, true, false, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.WinCtrl | KeyCode.Enter); - test(new SimpleKeybinding(true, true, true, false, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.Enter); - test(new SimpleKeybinding(true, true, true, true, KeyCode.Enter), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, false, false, false, KeyCode.Enter).toChord(), KeyCode.Enter); + test(new SimpleKeybinding(false, false, false, true, KeyCode.Enter).toChord(), KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, false, true, false, KeyCode.Enter).toChord(), KeyMod.Alt | KeyCode.Enter); + test(new SimpleKeybinding(false, false, true, true, KeyCode.Enter).toChord(), KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, true, false, false, KeyCode.Enter).toChord(), KeyMod.Shift | KeyCode.Enter); + test(new SimpleKeybinding(false, true, false, true, KeyCode.Enter).toChord(), KeyMod.Shift | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(false, true, true, false, KeyCode.Enter).toChord(), KeyMod.Shift | KeyMod.Alt | KeyCode.Enter); + test(new SimpleKeybinding(false, true, true, true, KeyCode.Enter).toChord(), KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(true, false, false, false, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyCode.Enter); + test(new SimpleKeybinding(true, false, false, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(true, false, true, false, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Enter); + test(new SimpleKeybinding(true, false, true, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(true, true, false, false, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter); + test(new SimpleKeybinding(true, true, false, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.WinCtrl | KeyCode.Enter); + test(new SimpleKeybinding(true, true, true, false, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.Enter); + test(new SimpleKeybinding(true, true, true, true, KeyCode.Enter).toChord(), KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.Enter); test( - new ChordKeybinding( + new ChordKeybinding([ new SimpleKeybinding(false, false, false, false, KeyCode.Enter), new SimpleKeybinding(false, false, false, false, KeyCode.Tab) - ), + ]), KeyChord(KeyCode.Enter, KeyCode.Tab) ); test( - new ChordKeybinding( + new ChordKeybinding([ new SimpleKeybinding(true, false, false, false, KeyCode.KEY_Y), new SimpleKeybinding(false, false, false, false, KeyCode.KEY_Z) - ), + ]), KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_Y, KeyCode.KEY_Z) ); diff --git a/src/vs/base/test/common/lifecycle.test.ts b/src/vs/base/test/common/lifecycle.test.ts index 29e93e64a41..46d8a254b5b 100644 --- a/src/vs/base/test/common/lifecycle.test.ts +++ b/src/vs/base/test/common/lifecycle.test.ts @@ -42,7 +42,8 @@ suite('Lifecycle', () => { assert(!disposable.isDisposed); assert(!disposable2.isDisposed); - dispose(disposable, disposable2); + dispose(disposable); + dispose(disposable2); assert(disposable.isDisposed); assert(disposable2.isDisposed); diff --git a/src/vs/base/test/common/linkedList.test.ts b/src/vs/base/test/common/linkedList.test.ts index 2de2286f885..7dc178dbbc0 100644 --- a/src/vs/base/test/common/linkedList.test.ts +++ b/src/vs/base/test/common/linkedList.test.ts @@ -52,6 +52,14 @@ suite('LinkedList', function () { disp = list.push(2); disp(); assertElements(list, 0, 1); + + list = new LinkedList(); + list.push(0); + list.push(1); + disp = list.push(2); + disp(); + disp(); + assertElements(list, 0, 1); }); test('Push/toArray', () => { diff --git a/src/vs/base/test/common/map.test.ts b/src/vs/base/test/common/map.test.ts index c179bdb34db..245cccdf776 100644 --- a/src/vs/base/test/common/map.test.ts +++ b/src/vs/base/test/common/map.test.ts @@ -226,6 +226,50 @@ suite('Map', () => { }); }); + test('LinkedMap - delete Head and Tail', function () { + const map = new LinkedMap(); + + assert.equal(map.size, 0); + + map.set('1', 1); + assert.equal(map.size, 1); + map.delete('1'); + assert.equal(map.get('1'), undefined); + assert.equal(map.size, 0); + assert.equal(map.keys().length, 0); + }); + + test('LinkedMap - delete Head', function () { + const map = new LinkedMap(); + + assert.equal(map.size, 0); + + map.set('1', 1); + map.set('2', 2); + assert.equal(map.size, 2); + map.delete('1'); + assert.equal(map.get('2'), 2); + assert.equal(map.size, 1); + assert.equal(map.keys().length, 1); + assert.equal(map.keys()[0], 2); + }); + + test('LinkedMap - delete Tail', function () { + const map = new LinkedMap(); + + assert.equal(map.size, 0); + + map.set('1', 1); + map.set('2', 2); + assert.equal(map.size, 2); + map.delete('2'); + assert.equal(map.get('1'), 1); + assert.equal(map.size, 1); + assert.equal(map.keys().length, 1); + assert.equal(map.keys()[0], 1); + }); + + test('PathIterator', () => { const iter = new PathIterator(); iter.reset('file:///usr/bin/file.txt'); diff --git a/src/vs/base/test/common/mime.test.ts b/src/vs/base/test/common/mime.test.ts index 75f6d531fe7..7c99c964c75 100644 --- a/src/vs/base/test/common/mime.test.ts +++ b/src/vs/base/test/common/mime.test.ts @@ -4,41 +4,43 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; import { guessMimeTypes, registerTextMime, suggestFilename } from 'vs/base/common/mime'; +import { URI } from 'vs/base/common/uri'; suite('Mime', () => { + test('Dynamically Register Text Mime', () => { - let guess = guessMimeTypes('foo.monaco'); + let guess = guessMimeTypes(URI.file('foo.monaco')); assert.deepEqual(guess, ['application/unknown']); registerTextMime({ id: 'monaco', extension: '.monaco', mime: 'text/monaco' }); - guess = guessMimeTypes('foo.monaco'); + guess = guessMimeTypes(URI.file('foo.monaco')); assert.deepEqual(guess, ['text/monaco', 'text/plain']); - guess = guessMimeTypes('.monaco'); + guess = guessMimeTypes(URI.file('.monaco')); assert.deepEqual(guess, ['text/monaco', 'text/plain']); registerTextMime({ id: 'codefile', filename: 'Codefile', mime: 'text/code' }); - guess = guessMimeTypes('Codefile'); + guess = guessMimeTypes(URI.file('Codefile')); assert.deepEqual(guess, ['text/code', 'text/plain']); - guess = guessMimeTypes('foo.Codefile'); + guess = guessMimeTypes(URI.file('foo.Codefile')); assert.deepEqual(guess, ['application/unknown']); registerTextMime({ id: 'docker', filepattern: 'Docker*', mime: 'text/docker' }); - guess = guessMimeTypes('Docker-debug'); + guess = guessMimeTypes(URI.file('Docker-debug')); assert.deepEqual(guess, ['text/docker', 'text/plain']); - guess = guessMimeTypes('docker-PROD'); + guess = guessMimeTypes(URI.file('docker-PROD')); assert.deepEqual(guess, ['text/docker', 'text/plain']); registerTextMime({ id: 'niceregex', mime: 'text/nice-regex', firstline: /RegexesAreNice/ }); - guess = guessMimeTypes('Randomfile.noregistration', 'RegexesAreNice'); + guess = guessMimeTypes(URI.file('Randomfile.noregistration'), 'RegexesAreNice'); assert.deepEqual(guess, ['text/nice-regex', 'text/plain']); - guess = guessMimeTypes('Randomfile.noregistration', 'RegexesAreNotNice'); + guess = guessMimeTypes(URI.file('Randomfile.noregistration'), 'RegexesAreNotNice'); assert.deepEqual(guess, ['application/unknown']); - guess = guessMimeTypes('Codefile', 'RegexesAreNice'); + guess = guessMimeTypes(URI.file('Codefile'), 'RegexesAreNice'); assert.deepEqual(guess, ['text/code', 'text/plain']); }); @@ -46,32 +48,37 @@ suite('Mime', () => { registerTextMime({ id: 'monaco', extension: '.monaco', mime: 'text/monaco' }); registerTextMime({ id: 'foobar', mime: 'text/foobar', firstline: /foobar/ }); - let guess = guessMimeTypes('foo.monaco'); + let guess = guessMimeTypes(URI.file('foo.monaco')); assert.deepEqual(guess, ['text/monaco', 'text/plain']); - guess = guessMimeTypes('foo.monaco', 'foobar'); + guess = guessMimeTypes(URI.file('foo.monaco'), 'foobar'); assert.deepEqual(guess, ['text/monaco', 'text/plain']); registerTextMime({ id: 'docker', filename: 'dockerfile', mime: 'text/winner' }); registerTextMime({ id: 'docker', filepattern: 'dockerfile*', mime: 'text/looser' }); - guess = guessMimeTypes('dockerfile'); + guess = guessMimeTypes(URI.file('dockerfile')); assert.deepEqual(guess, ['text/winner', 'text/plain']); + + registerTextMime({ id: 'azure-looser', mime: 'text/azure-looser', firstline: /azure/ }); + registerTextMime({ id: 'azure-winner', mime: 'text/azure-winner', firstline: /azure/ }); + guess = guessMimeTypes(URI.file('azure'), 'azure'); + assert.deepEqual(guess, ['text/azure-winner', 'text/plain']); }); test('Specificity priority 1', () => { registerTextMime({ id: 'monaco2', extension: '.monaco2', mime: 'text/monaco2' }); registerTextMime({ id: 'monaco2', filename: 'specific.monaco2', mime: 'text/specific-monaco2' }); - assert.deepEqual(guessMimeTypes('specific.monaco2'), ['text/specific-monaco2', 'text/plain']); - assert.deepEqual(guessMimeTypes('foo.monaco2'), ['text/monaco2', 'text/plain']); + assert.deepEqual(guessMimeTypes(URI.file('specific.monaco2')), ['text/specific-monaco2', 'text/plain']); + assert.deepEqual(guessMimeTypes(URI.file('foo.monaco2')), ['text/monaco2', 'text/plain']); }); test('Specificity priority 2', () => { registerTextMime({ id: 'monaco3', filename: 'specific.monaco3', mime: 'text/specific-monaco3' }); registerTextMime({ id: 'monaco3', extension: '.monaco3', mime: 'text/monaco3' }); - assert.deepEqual(guessMimeTypes('specific.monaco3'), ['text/specific-monaco3', 'text/plain']); - assert.deepEqual(guessMimeTypes('foo.monaco3'), ['text/monaco3', 'text/plain']); + assert.deepEqual(guessMimeTypes(URI.file('specific.monaco3')), ['text/specific-monaco3', 'text/plain']); + assert.deepEqual(guessMimeTypes(URI.file('foo.monaco3')), ['text/monaco3', 'text/plain']); }); test('Mimes Priority - Longest Extension wins', () => { @@ -79,13 +86,13 @@ suite('Mime', () => { registerTextMime({ id: 'monaco', extension: '.monaco.xml', mime: 'text/monaco-xml' }); registerTextMime({ id: 'monaco', extension: '.monaco.xml.build', mime: 'text/monaco-xml-build' }); - let guess = guessMimeTypes('foo.monaco'); + let guess = guessMimeTypes(URI.file('foo.monaco')); assert.deepEqual(guess, ['text/monaco', 'text/plain']); - guess = guessMimeTypes('foo.monaco.xml'); + guess = guessMimeTypes(URI.file('foo.monaco.xml')); assert.deepEqual(guess, ['text/monaco-xml', 'text/plain']); - guess = guessMimeTypes('foo.monaco.xml.build'); + guess = guessMimeTypes(URI.file('foo.monaco.xml.build')); assert.deepEqual(guess, ['text/monaco-xml-build', 'text/plain']); }); @@ -93,7 +100,7 @@ suite('Mime', () => { registerTextMime({ id: 'monaco', extension: '.monaco.xnl', mime: 'text/monaco', userConfigured: true }); registerTextMime({ id: 'monaco', extension: '.monaco.xml', mime: 'text/monaco-xml' }); - let guess = guessMimeTypes('foo.monaco.xnl'); + let guess = guessMimeTypes(URI.file('foo.monaco.xnl')); assert.deepEqual(guess, ['text/monaco', 'text/plain']); }); @@ -101,7 +108,7 @@ suite('Mime', () => { registerTextMime({ id: 'monaco', filepattern: '**/dot.monaco.xml', mime: 'text/monaco' }); registerTextMime({ id: 'other', filepattern: '*ot.other.xml', mime: 'text/other' }); - let guess = guessMimeTypes('/some/path/dot.monaco.xml'); + let guess = guessMimeTypes(URI.file('/some/path/dot.monaco.xml')); assert.deepEqual(guess, ['text/monaco', 'text/plain']); }); @@ -109,10 +116,16 @@ suite('Mime', () => { registerTextMime({ id: 'monaco', filepattern: '**/dot.monaco.xml', mime: 'text/monaco' }); registerTextMime({ id: 'other', filepattern: '**/dot.monaco.xml', mime: 'text/other' }); - let guess = guessMimeTypes('/some/path/dot.monaco.xml'); + let guess = guessMimeTypes(URI.file('/some/path/dot.monaco.xml')); assert.deepEqual(guess, ['text/other', 'text/plain']); }); + test('Data URIs', () => { + registerTextMime({ id: 'data', extension: '.data', mime: 'text/data' }); + + assert.deepEqual(guessMimeTypes(URI.parse(`data:;label:something.data;description:data,`)), ['text/data', 'text/plain']); + }); + test('Filename Suggestion - Suggest prefix only when there are no relevant extensions', () => { const id = 'plumbus0'; const mime = `text/${id}`; diff --git a/src/vs/base/test/common/path.test.ts b/src/vs/base/test/common/path.test.ts new file mode 100644 index 00000000000..cfceaedc9e9 --- /dev/null +++ b/src/vs/base/test/common/path.test.ts @@ -0,0 +1,824 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// NOTE: VSCode's copy of nodejs path library to be usable in common (non-node) namespace +// Copied from: https://github.com/nodejs/node/tree/43dd49c9782848c25e5b03448c8a0f923f13c158 + +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +import * as assert from 'assert'; +import * as path from 'vs/base/common/path'; +import { isWindows } from 'vs/base/common/platform'; + +suite('Paths (Node Implementation)', () => { + test('join', () => { + const failures = [] as string[]; + const backslashRE = /\\/g; + + const joinTests: any = [ + [[path.posix.join, path.win32.join], + // arguments result + [[['.', 'x/b', '..', '/b/c.js'], 'x/b/c.js'], + [[], '.'], + [['/.', 'x/b', '..', '/b/c.js'], '/x/b/c.js'], + [['/foo', '../../../bar'], '/bar'], + [['foo', '../../../bar'], '../../bar'], + [['foo/', '../../../bar'], '../../bar'], + [['foo/x', '../../../bar'], '../bar'], + [['foo/x', './bar'], 'foo/x/bar'], + [['foo/x/', './bar'], 'foo/x/bar'], + [['foo/x/', '.', 'bar'], 'foo/x/bar'], + [['./'], './'], + [['.', './'], './'], + [['.', '.', '.'], '.'], + [['.', './', '.'], '.'], + [['.', '/./', '.'], '.'], + [['.', '/////./', '.'], '.'], + [['.'], '.'], + [['', '.'], '.'], + [['', 'foo'], 'foo'], + [['foo', '/bar'], 'foo/bar'], + [['', '/foo'], '/foo'], + [['', '', '/foo'], '/foo'], + [['', '', 'foo'], 'foo'], + [['foo', ''], 'foo'], + [['foo/', ''], 'foo/'], + [['foo', '', '/bar'], 'foo/bar'], + [['./', '..', '/foo'], '../foo'], + [['./', '..', '..', '/foo'], '../../foo'], + [['.', '..', '..', '/foo'], '../../foo'], + [['', '..', '..', '/foo'], '../../foo'], + [['/'], '/'], + [['/', '.'], '/'], + [['/', '..'], '/'], + [['/', '..', '..'], '/'], + [[''], '.'], + [['', ''], '.'], + [[' /foo'], ' /foo'], + [[' ', 'foo'], ' /foo'], + [[' ', '.'], ' '], + [[' ', '/'], ' /'], + [[' ', ''], ' '], + [['/', 'foo'], '/foo'], + [['/', '/foo'], '/foo'], + [['/', '//foo'], '/foo'], + [['/', '', '/foo'], '/foo'], + [['', '/', 'foo'], '/foo'], + [['', '/', '/foo'], '/foo'] + ] + ] + ]; + + // Windows-specific join tests + joinTests.push([ + path.win32.join, + joinTests[0][1].slice(0).concat( + [// arguments result + // UNC path expected + [['//foo/bar'], '\\\\foo\\bar\\'], + [['\\/foo/bar'], '\\\\foo\\bar\\'], + [['\\\\foo/bar'], '\\\\foo\\bar\\'], + // UNC path expected - server and share separate + [['//foo', 'bar'], '\\\\foo\\bar\\'], + [['//foo/', 'bar'], '\\\\foo\\bar\\'], + [['//foo', '/bar'], '\\\\foo\\bar\\'], + // UNC path expected - questionable + [['//foo', '', 'bar'], '\\\\foo\\bar\\'], + [['//foo/', '', 'bar'], '\\\\foo\\bar\\'], + [['//foo/', '', '/bar'], '\\\\foo\\bar\\'], + // UNC path expected - even more questionable + [['', '//foo', 'bar'], '\\\\foo\\bar\\'], + [['', '//foo/', 'bar'], '\\\\foo\\bar\\'], + [['', '//foo/', '/bar'], '\\\\foo\\bar\\'], + // No UNC path expected (no double slash in first component) + [['\\', 'foo/bar'], '\\foo\\bar'], + [['\\', '/foo/bar'], '\\foo\\bar'], + [['', '/', '/foo/bar'], '\\foo\\bar'], + // No UNC path expected (no non-slashes in first component - + // questionable) + [['//', 'foo/bar'], '\\foo\\bar'], + [['//', '/foo/bar'], '\\foo\\bar'], + [['\\\\', '/', '/foo/bar'], '\\foo\\bar'], + [['//'], '\\'], + // No UNC path expected (share name missing - questionable). + [['//foo'], '\\foo'], + [['//foo/'], '\\foo\\'], + [['//foo', '/'], '\\foo\\'], + [['//foo', '', '/'], '\\foo\\'], + // No UNC path expected (too many leading slashes - questionable) + [['///foo/bar'], '\\foo\\bar'], + [['////foo', 'bar'], '\\foo\\bar'], + [['\\\\\\/foo/bar'], '\\foo\\bar'], + // Drive-relative vs drive-absolute paths. This merely describes the + // status quo, rather than being obviously right + [['c:'], 'c:.'], + [['c:.'], 'c:.'], + [['c:', ''], 'c:.'], + [['', 'c:'], 'c:.'], + [['c:.', '/'], 'c:.\\'], + [['c:.', 'file'], 'c:file'], + [['c:', '/'], 'c:\\'], + [['c:', 'file'], 'c:\\file'] + ] + ) + ]); + joinTests.forEach((test: any[]) => { + if (!Array.isArray(test[0])) { + test[0] = [test[0]]; + } + test[0].forEach((join: any) => { + test[1].forEach((test: any) => { + const actual = join.apply(null, test[0]); + const expected = test[1]; + // For non-Windows specific tests with the Windows join(), we need to try + // replacing the slashes since the non-Windows specific tests' `expected` + // use forward slashes + let actualAlt; + let os; + if (join === path.win32.join) { + actualAlt = actual.replace(backslashRE, '/'); + os = 'win32'; + } else { + os = 'posix'; + } + const message = + `path.${os}.join(${test[0].map(JSON.stringify).join(',')})\n expect=${ + JSON.stringify(expected)}\n actual=${JSON.stringify(actual)}`; + if (actual !== expected && actualAlt !== expected) { + failures.push(`\n${message}`); + } + }); + }); + }); + assert.strictEqual(failures.length, 0, failures.join('')); + }); + + test('dirname', () => { + assert.strictEqual(path.dirname(path.normalize(__filename)).substr(-11), + isWindows ? 'test\\common' : 'test/common'); + + assert.strictEqual(path.posix.dirname('/a/b/'), '/a'); + assert.strictEqual(path.posix.dirname('/a/b'), '/a'); + assert.strictEqual(path.posix.dirname('/a'), '/'); + assert.strictEqual(path.posix.dirname(''), '.'); + assert.strictEqual(path.posix.dirname('/'), '/'); + assert.strictEqual(path.posix.dirname('////'), '/'); + assert.strictEqual(path.posix.dirname('//a'), '//'); + assert.strictEqual(path.posix.dirname('foo'), '.'); + + assert.strictEqual(path.win32.dirname('c:\\'), 'c:\\'); + assert.strictEqual(path.win32.dirname('c:\\foo'), 'c:\\'); + assert.strictEqual(path.win32.dirname('c:\\foo\\'), 'c:\\'); + assert.strictEqual(path.win32.dirname('c:\\foo\\bar'), 'c:\\foo'); + assert.strictEqual(path.win32.dirname('c:\\foo\\bar\\'), 'c:\\foo'); + assert.strictEqual(path.win32.dirname('c:\\foo\\bar\\baz'), 'c:\\foo\\bar'); + assert.strictEqual(path.win32.dirname('\\'), '\\'); + assert.strictEqual(path.win32.dirname('\\foo'), '\\'); + assert.strictEqual(path.win32.dirname('\\foo\\'), '\\'); + assert.strictEqual(path.win32.dirname('\\foo\\bar'), '\\foo'); + assert.strictEqual(path.win32.dirname('\\foo\\bar\\'), '\\foo'); + assert.strictEqual(path.win32.dirname('\\foo\\bar\\baz'), '\\foo\\bar'); + assert.strictEqual(path.win32.dirname('c:'), 'c:'); + assert.strictEqual(path.win32.dirname('c:foo'), 'c:'); + assert.strictEqual(path.win32.dirname('c:foo\\'), 'c:'); + assert.strictEqual(path.win32.dirname('c:foo\\bar'), 'c:foo'); + assert.strictEqual(path.win32.dirname('c:foo\\bar\\'), 'c:foo'); + assert.strictEqual(path.win32.dirname('c:foo\\bar\\baz'), 'c:foo\\bar'); + assert.strictEqual(path.win32.dirname('file:stream'), '.'); + assert.strictEqual(path.win32.dirname('dir\\file:stream'), 'dir'); + assert.strictEqual(path.win32.dirname('\\\\unc\\share'), + '\\\\unc\\share'); + assert.strictEqual(path.win32.dirname('\\\\unc\\share\\foo'), + '\\\\unc\\share\\'); + assert.strictEqual(path.win32.dirname('\\\\unc\\share\\foo\\'), + '\\\\unc\\share\\'); + assert.strictEqual(path.win32.dirname('\\\\unc\\share\\foo\\bar'), + '\\\\unc\\share\\foo'); + assert.strictEqual(path.win32.dirname('\\\\unc\\share\\foo\\bar\\'), + '\\\\unc\\share\\foo'); + assert.strictEqual(path.win32.dirname('\\\\unc\\share\\foo\\bar\\baz'), + '\\\\unc\\share\\foo\\bar'); + assert.strictEqual(path.win32.dirname('/a/b/'), '/a'); + assert.strictEqual(path.win32.dirname('/a/b'), '/a'); + assert.strictEqual(path.win32.dirname('/a'), '/'); + assert.strictEqual(path.win32.dirname(''), '.'); + assert.strictEqual(path.win32.dirname('/'), '/'); + assert.strictEqual(path.win32.dirname('////'), '/'); + assert.strictEqual(path.win32.dirname('foo'), '.'); + + // Tests from VSCode + + function assertDirname(p: string, expected: string, win = false) { + const actual = win ? path.win32.dirname(p) : path.posix.dirname(p); + + if (actual !== expected) { + assert.fail(`${p}: expected: ${expected}, ours: ${actual}`); + } + } + + assertDirname('foo/bar', 'foo'); + assertDirname('foo\\bar', 'foo', true); + assertDirname('/foo/bar', '/foo'); + assertDirname('\\foo\\bar', '\\foo', true); + assertDirname('/foo', '/'); + assertDirname('\\foo', '\\', true); + assertDirname('/', '/'); + assertDirname('\\', '\\', true); + assertDirname('foo', '.'); + assertDirname('f', '.'); + assertDirname('f/', '.'); + assertDirname('/folder/', '/'); + assertDirname('c:\\some\\file.txt', 'c:\\some', true); + assertDirname('c:\\some', 'c:\\', true); + assertDirname('c:\\', 'c:\\', true); + assertDirname('c:', 'c:', true); + assertDirname('\\\\server\\share\\some\\path', '\\\\server\\share\\some', true); + assertDirname('\\\\server\\share\\some', '\\\\server\\share\\', true); + assertDirname('\\\\server\\share\\', '\\\\server\\share\\', true); + }); + + test('extname', () => { + const failures = [] as string[]; + const slashRE = /\//g; + + [ + [__filename, '.js'], + ['', ''], + ['/path/to/file', ''], + ['/path/to/file.ext', '.ext'], + ['/path.to/file.ext', '.ext'], + ['/path.to/file', ''], + ['/path.to/.file', ''], + ['/path.to/.file.ext', '.ext'], + ['/path/to/f.ext', '.ext'], + ['/path/to/..ext', '.ext'], + ['/path/to/..', ''], + ['file', ''], + ['file.ext', '.ext'], + ['.file', ''], + ['.file.ext', '.ext'], + ['/file', ''], + ['/file.ext', '.ext'], + ['/.file', ''], + ['/.file.ext', '.ext'], + ['.path/file.ext', '.ext'], + ['file.ext.ext', '.ext'], + ['file.', '.'], + ['.', ''], + ['./', ''], + ['.file.ext', '.ext'], + ['.file', ''], + ['.file.', '.'], + ['.file..', '.'], + ['..', ''], + ['../', ''], + ['..file.ext', '.ext'], + ['..file', '.file'], + ['..file.', '.'], + ['..file..', '.'], + ['...', '.'], + ['...ext', '.ext'], + ['....', '.'], + ['file.ext/', '.ext'], + ['file.ext//', '.ext'], + ['file/', ''], + ['file//', ''], + ['file./', '.'], + ['file.//', '.'], + ].forEach((test) => { + const expected = test[1]; + [path.posix.extname, path.win32.extname].forEach((extname) => { + let input = test[0]; + let os; + if (extname === path.win32.extname) { + input = input.replace(slashRE, '\\'); + os = 'win32'; + } else { + os = 'posix'; + } + const actual = extname(input); + const message = `path.${os}.extname(${JSON.stringify(input)})\n expect=${ + JSON.stringify(expected)}\n actual=${JSON.stringify(actual)}`; + if (actual !== expected) { + failures.push(`\n${message}`); + } + }); + { + const input = `C:${test[0].replace(slashRE, '\\')}`; + const actual = path.win32.extname(input); + const message = `path.win32.extname(${JSON.stringify(input)})\n expect=${ + JSON.stringify(expected)}\n actual=${JSON.stringify(actual)}`; + if (actual !== expected) { + failures.push(`\n${message}`); + } + } + }); + assert.strictEqual(failures.length, 0, failures.join('')); + + // On Windows, backslash is a path separator. + assert.strictEqual(path.win32.extname('.\\'), ''); + assert.strictEqual(path.win32.extname('..\\'), ''); + assert.strictEqual(path.win32.extname('file.ext\\'), '.ext'); + assert.strictEqual(path.win32.extname('file.ext\\\\'), '.ext'); + assert.strictEqual(path.win32.extname('file\\'), ''); + assert.strictEqual(path.win32.extname('file\\\\'), ''); + assert.strictEqual(path.win32.extname('file.\\'), '.'); + assert.strictEqual(path.win32.extname('file.\\\\'), '.'); + + // On *nix, backslash is a valid name component like any other character. + assert.strictEqual(path.posix.extname('.\\'), ''); + assert.strictEqual(path.posix.extname('..\\'), '.\\'); + assert.strictEqual(path.posix.extname('file.ext\\'), '.ext\\'); + assert.strictEqual(path.posix.extname('file.ext\\\\'), '.ext\\\\'); + assert.strictEqual(path.posix.extname('file\\'), ''); + assert.strictEqual(path.posix.extname('file\\\\'), ''); + assert.strictEqual(path.posix.extname('file.\\'), '.\\'); + assert.strictEqual(path.posix.extname('file.\\\\'), '.\\\\'); + + // Tests from VSCode + assert.equal(path.extname('far.boo'), '.boo'); + assert.equal(path.extname('far.b'), '.b'); + assert.equal(path.extname('far.'), '.'); + assert.equal(path.extname('far.boo/boo.far'), '.far'); + assert.equal(path.extname('far.boo/boo'), ''); + }); + + test('resolve', () => { + const failures = [] as string[]; + const slashRE = /\//g; + const backslashRE = /\\/g; + + const resolveTests = [ + [path.win32.resolve, + // arguments result + [[['c:/blah\\blah', 'd:/games', 'c:../a'], 'c:\\blah\\a'], + [['c:/ignore', 'd:\\a/b\\c/d', '\\e.exe'], 'd:\\e.exe'], + [['c:/ignore', 'c:/some/file'], 'c:\\some\\file'], + [['d:/ignore', 'd:some/dir//'], 'd:\\ignore\\some\\dir'], + [['.'], process.cwd()], + [['//server/share', '..', 'relative\\'], '\\\\server\\share\\relative'], + [['c:/', '//'], 'c:\\'], + [['c:/', '//dir'], 'c:\\dir'], + [['c:/', '//server/share'], '\\\\server\\share\\'], + [['c:/', '//server//share'], '\\\\server\\share\\'], + [['c:/', '///some//dir'], 'c:\\some\\dir'], + [['C:\\foo\\tmp.3\\', '..\\tmp.3\\cycles\\root.js'], + 'C:\\foo\\tmp.3\\cycles\\root.js'] + ] + ], + [path.posix.resolve, + // arguments result + [[['/var/lib', '../', 'file/'], '/var/file'], + [['/var/lib', '/../', 'file/'], '/file'], + [['a/b/c/', '../../..'], process.cwd()], + [['.'], process.cwd()], + [['/some/dir', '.', '/absolute/'], '/absolute'], + [['/foo/tmp.3/', '../tmp.3/cycles/root.js'], '/foo/tmp.3/cycles/root.js'] + ] + ] + ]; + resolveTests.forEach((test) => { + const resolve = test[0]; + //@ts-ignore + test[1].forEach((test) => { + //@ts-ignore + const actual = resolve.apply(null, test[0]); + let actualAlt; + const os = resolve === path.win32.resolve ? 'win32' : 'posix'; + if (resolve === path.win32.resolve && !isWindows) { + actualAlt = actual.replace(backslashRE, '/'); + } + else if (resolve !== path.win32.resolve && isWindows) { + actualAlt = actual.replace(slashRE, '\\'); + } + + const expected = test[1]; + const message = + `path.${os}.resolve(${test[0].map(JSON.stringify).join(',')})\n expect=${ + JSON.stringify(expected)}\n actual=${JSON.stringify(actual)}`; + if (actual !== expected && actualAlt !== expected) { + failures.push(`\n${message}`); + } + }); + }); + assert.strictEqual(failures.length, 0, failures.join('')); + + // if (isWindows) { + // // Test resolving the current Windows drive letter from a spawned process. + // // See https://github.com/nodejs/node/issues/7215 + // const currentDriveLetter = path.parse(process.cwd()).root.substring(0, 2); + // const resolveFixture = fixtures.path('path-resolve.js'); + // const spawnResult = child.spawnSync( + // process.argv[0], [resolveFixture, currentDriveLetter]); + // const resolvedPath = spawnResult.stdout.toString().trim(); + // assert.strictEqual(resolvedPath.toLowerCase(), process.cwd().toLowerCase()); + // } + }); + + test('basename', () => { + assert.strictEqual(path.basename(__filename), 'path.test.js'); + assert.strictEqual(path.basename(__filename, '.js'), 'path.test'); + assert.strictEqual(path.basename('.js', '.js'), ''); + assert.strictEqual(path.basename(''), ''); + assert.strictEqual(path.basename('/dir/basename.ext'), 'basename.ext'); + assert.strictEqual(path.basename('/basename.ext'), 'basename.ext'); + assert.strictEqual(path.basename('basename.ext'), 'basename.ext'); + assert.strictEqual(path.basename('basename.ext/'), 'basename.ext'); + assert.strictEqual(path.basename('basename.ext//'), 'basename.ext'); + assert.strictEqual(path.basename('aaa/bbb', '/bbb'), 'bbb'); + assert.strictEqual(path.basename('aaa/bbb', 'a/bbb'), 'bbb'); + assert.strictEqual(path.basename('aaa/bbb', 'bbb'), 'bbb'); + assert.strictEqual(path.basename('aaa/bbb//', 'bbb'), 'bbb'); + assert.strictEqual(path.basename('aaa/bbb', 'bb'), 'b'); + assert.strictEqual(path.basename('aaa/bbb', 'b'), 'bb'); + assert.strictEqual(path.basename('/aaa/bbb', '/bbb'), 'bbb'); + assert.strictEqual(path.basename('/aaa/bbb', 'a/bbb'), 'bbb'); + assert.strictEqual(path.basename('/aaa/bbb', 'bbb'), 'bbb'); + assert.strictEqual(path.basename('/aaa/bbb//', 'bbb'), 'bbb'); + assert.strictEqual(path.basename('/aaa/bbb', 'bb'), 'b'); + assert.strictEqual(path.basename('/aaa/bbb', 'b'), 'bb'); + assert.strictEqual(path.basename('/aaa/bbb'), 'bbb'); + assert.strictEqual(path.basename('/aaa/'), 'aaa'); + assert.strictEqual(path.basename('/aaa/b'), 'b'); + assert.strictEqual(path.basename('/a/b'), 'b'); + assert.strictEqual(path.basename('//a'), 'a'); + assert.strictEqual(path.basename('a', 'a'), ''); + + // On Windows a backslash acts as a path separator. + assert.strictEqual(path.win32.basename('\\dir\\basename.ext'), 'basename.ext'); + assert.strictEqual(path.win32.basename('\\basename.ext'), 'basename.ext'); + assert.strictEqual(path.win32.basename('basename.ext'), 'basename.ext'); + assert.strictEqual(path.win32.basename('basename.ext\\'), 'basename.ext'); + assert.strictEqual(path.win32.basename('basename.ext\\\\'), 'basename.ext'); + assert.strictEqual(path.win32.basename('foo'), 'foo'); + assert.strictEqual(path.win32.basename('aaa\\bbb', '\\bbb'), 'bbb'); + assert.strictEqual(path.win32.basename('aaa\\bbb', 'a\\bbb'), 'bbb'); + assert.strictEqual(path.win32.basename('aaa\\bbb', 'bbb'), 'bbb'); + assert.strictEqual(path.win32.basename('aaa\\bbb\\\\\\\\', 'bbb'), 'bbb'); + assert.strictEqual(path.win32.basename('aaa\\bbb', 'bb'), 'b'); + assert.strictEqual(path.win32.basename('aaa\\bbb', 'b'), 'bb'); + assert.strictEqual(path.win32.basename('C:'), ''); + assert.strictEqual(path.win32.basename('C:.'), '.'); + assert.strictEqual(path.win32.basename('C:\\'), ''); + assert.strictEqual(path.win32.basename('C:\\dir\\base.ext'), 'base.ext'); + assert.strictEqual(path.win32.basename('C:\\basename.ext'), 'basename.ext'); + assert.strictEqual(path.win32.basename('C:basename.ext'), 'basename.ext'); + assert.strictEqual(path.win32.basename('C:basename.ext\\'), 'basename.ext'); + assert.strictEqual(path.win32.basename('C:basename.ext\\\\'), 'basename.ext'); + assert.strictEqual(path.win32.basename('C:foo'), 'foo'); + assert.strictEqual(path.win32.basename('file:stream'), 'file:stream'); + assert.strictEqual(path.win32.basename('a', 'a'), ''); + + // On unix a backslash is just treated as any other character. + assert.strictEqual(path.posix.basename('\\dir\\basename.ext'), + '\\dir\\basename.ext'); + assert.strictEqual(path.posix.basename('\\basename.ext'), '\\basename.ext'); + assert.strictEqual(path.posix.basename('basename.ext'), 'basename.ext'); + assert.strictEqual(path.posix.basename('basename.ext\\'), 'basename.ext\\'); + assert.strictEqual(path.posix.basename('basename.ext\\\\'), 'basename.ext\\\\'); + assert.strictEqual(path.posix.basename('foo'), 'foo'); + + // POSIX filenames may include control characters + // c.f. http://www.dwheeler.com/essays/fixing-unix-linux-filenames.html + const controlCharFilename = `Icon${String.fromCharCode(13)}`; + assert.strictEqual(path.posix.basename(`/a/b/${controlCharFilename}`), + controlCharFilename); + + // Tests from VSCode + assert.equal(path.basename('foo/bar'), 'bar'); + assert.equal(path.posix.basename('foo\\bar'), 'foo\\bar'); + assert.equal(path.win32.basename('foo\\bar'), 'bar'); + assert.equal(path.basename('/foo/bar'), 'bar'); + assert.equal(path.posix.basename('\\foo\\bar'), '\\foo\\bar'); + assert.equal(path.win32.basename('\\foo\\bar'), 'bar'); + assert.equal(path.basename('./bar'), 'bar'); + assert.equal(path.posix.basename('.\\bar'), '.\\bar'); + assert.equal(path.win32.basename('.\\bar'), 'bar'); + assert.equal(path.basename('/bar'), 'bar'); + assert.equal(path.posix.basename('\\bar'), '\\bar'); + assert.equal(path.win32.basename('\\bar'), 'bar'); + assert.equal(path.basename('bar/'), 'bar'); + assert.equal(path.posix.basename('bar\\'), 'bar\\'); + assert.equal(path.win32.basename('bar\\'), 'bar'); + assert.equal(path.basename('bar'), 'bar'); + assert.equal(path.basename('////////'), ''); + assert.equal(path.posix.basename('\\\\\\\\'), '\\\\\\\\'); + assert.equal(path.win32.basename('\\\\\\\\'), ''); + }); + + test('relative', () => { + const failures = [] as string[]; + + const relativeTests = [ + [path.win32.relative, + // arguments result + [['c:/blah\\blah', 'd:/games', 'd:\\games'], + ['c:/aaaa/bbbb', 'c:/aaaa', '..'], + ['c:/aaaa/bbbb', 'c:/cccc', '..\\..\\cccc'], + ['c:/aaaa/bbbb', 'c:/aaaa/bbbb', ''], + ['c:/aaaa/bbbb', 'c:/aaaa/cccc', '..\\cccc'], + ['c:/aaaa/', 'c:/aaaa/cccc', 'cccc'], + ['c:/', 'c:\\aaaa\\bbbb', 'aaaa\\bbbb'], + ['c:/aaaa/bbbb', 'd:\\', 'd:\\'], + ['c:/AaAa/bbbb', 'c:/aaaa/bbbb', ''], + ['c:/aaaaa/', 'c:/aaaa/cccc', '..\\aaaa\\cccc'], + ['C:\\foo\\bar\\baz\\quux', 'C:\\', '..\\..\\..\\..'], + ['C:\\foo\\test', 'C:\\foo\\test\\bar\\package.json', 'bar\\package.json'], + ['C:\\foo\\bar\\baz-quux', 'C:\\foo\\bar\\baz', '..\\baz'], + ['C:\\foo\\bar\\baz', 'C:\\foo\\bar\\baz-quux', '..\\baz-quux'], + ['\\\\foo\\bar', '\\\\foo\\bar\\baz', 'baz'], + ['\\\\foo\\bar\\baz', '\\\\foo\\bar', '..'], + ['\\\\foo\\bar\\baz-quux', '\\\\foo\\bar\\baz', '..\\baz'], + ['\\\\foo\\bar\\baz', '\\\\foo\\bar\\baz-quux', '..\\baz-quux'], + ['C:\\baz-quux', 'C:\\baz', '..\\baz'], + ['C:\\baz', 'C:\\baz-quux', '..\\baz-quux'], + ['\\\\foo\\baz-quux', '\\\\foo\\baz', '..\\baz'], + ['\\\\foo\\baz', '\\\\foo\\baz-quux', '..\\baz-quux'], + ['C:\\baz', '\\\\foo\\bar\\baz', '\\\\foo\\bar\\baz'], + ['\\\\foo\\bar\\baz', 'C:\\baz', 'C:\\baz'] + ] + ], + [path.posix.relative, + // arguments result + [['/var/lib', '/var', '..'], + ['/var/lib', '/bin', '../../bin'], + ['/var/lib', '/var/lib', ''], + ['/var/lib', '/var/apache', '../apache'], + ['/var/', '/var/lib', 'lib'], + ['/', '/var/lib', 'var/lib'], + ['/foo/test', '/foo/test/bar/package.json', 'bar/package.json'], + ['/Users/a/web/b/test/mails', '/Users/a/web/b', '../..'], + ['/foo/bar/baz-quux', '/foo/bar/baz', '../baz'], + ['/foo/bar/baz', '/foo/bar/baz-quux', '../baz-quux'], + ['/baz-quux', '/baz', '../baz'], + ['/baz', '/baz-quux', '../baz-quux'] + ] + ] + ]; + relativeTests.forEach((test) => { + const relative = test[0]; + //@ts-ignore + test[1].forEach((test) => { + //@ts-ignore + const actual = relative(test[0], test[1]); + const expected = test[2]; + const os = relative === path.win32.relative ? 'win32' : 'posix'; + const message = `path.${os}.relative(${ + test.slice(0, 2).map(JSON.stringify).join(',')})\n expect=${ + JSON.stringify(expected)}\n actual=${JSON.stringify(actual)}`; + if (actual !== expected) { + failures.push(`\n${message}`); + } + }); + }); + assert.strictEqual(failures.length, 0, failures.join('')); + }); + + test('normalize', () => { + assert.strictEqual(path.win32.normalize('./fixtures///b/../b/c.js'), + 'fixtures\\b\\c.js'); + assert.strictEqual(path.win32.normalize('/foo/../../../bar'), '\\bar'); + assert.strictEqual(path.win32.normalize('a//b//../b'), 'a\\b'); + assert.strictEqual(path.win32.normalize('a//b//./c'), 'a\\b\\c'); + assert.strictEqual(path.win32.normalize('a//b//.'), 'a\\b'); + assert.strictEqual(path.win32.normalize('//server/share/dir/file.ext'), + '\\\\server\\share\\dir\\file.ext'); + assert.strictEqual(path.win32.normalize('/a/b/c/../../../x/y/z'), '\\x\\y\\z'); + assert.strictEqual(path.win32.normalize('C:'), 'C:.'); + assert.strictEqual(path.win32.normalize('C:..\\abc'), 'C:..\\abc'); + assert.strictEqual(path.win32.normalize('C:..\\..\\abc\\..\\def'), + 'C:..\\..\\def'); + assert.strictEqual(path.win32.normalize('C:\\.'), 'C:\\'); + assert.strictEqual(path.win32.normalize('file:stream'), 'file:stream'); + assert.strictEqual(path.win32.normalize('bar\\foo..\\..\\'), 'bar\\'); + assert.strictEqual(path.win32.normalize('bar\\foo..\\..'), 'bar'); + assert.strictEqual(path.win32.normalize('bar\\foo..\\..\\baz'), 'bar\\baz'); + assert.strictEqual(path.win32.normalize('bar\\foo..\\'), 'bar\\foo..\\'); + assert.strictEqual(path.win32.normalize('bar\\foo..'), 'bar\\foo..'); + assert.strictEqual(path.win32.normalize('..\\foo..\\..\\..\\bar'), + '..\\..\\bar'); + assert.strictEqual(path.win32.normalize('..\\...\\..\\.\\...\\..\\..\\bar'), + '..\\..\\bar'); + assert.strictEqual(path.win32.normalize('../../../foo/../../../bar'), + '..\\..\\..\\..\\..\\bar'); + assert.strictEqual(path.win32.normalize('../../../foo/../../../bar/../../'), + '..\\..\\..\\..\\..\\..\\'); + assert.strictEqual( + path.win32.normalize('../foobar/barfoo/foo/../../../bar/../../'), + '..\\..\\' + ); + assert.strictEqual( + path.win32.normalize('../.../../foobar/../../../bar/../../baz'), + '..\\..\\..\\..\\baz' + ); + assert.strictEqual(path.win32.normalize('foo/bar\\baz'), 'foo\\bar\\baz'); + + assert.strictEqual(path.posix.normalize('./fixtures///b/../b/c.js'), + 'fixtures/b/c.js'); + assert.strictEqual(path.posix.normalize('/foo/../../../bar'), '/bar'); + assert.strictEqual(path.posix.normalize('a//b//../b'), 'a/b'); + assert.strictEqual(path.posix.normalize('a//b//./c'), 'a/b/c'); + assert.strictEqual(path.posix.normalize('a//b//.'), 'a/b'); + assert.strictEqual(path.posix.normalize('/a/b/c/../../../x/y/z'), '/x/y/z'); + assert.strictEqual(path.posix.normalize('///..//./foo/.//bar'), '/foo/bar'); + assert.strictEqual(path.posix.normalize('bar/foo../../'), 'bar/'); + assert.strictEqual(path.posix.normalize('bar/foo../..'), 'bar'); + assert.strictEqual(path.posix.normalize('bar/foo../../baz'), 'bar/baz'); + assert.strictEqual(path.posix.normalize('bar/foo../'), 'bar/foo../'); + assert.strictEqual(path.posix.normalize('bar/foo..'), 'bar/foo..'); + assert.strictEqual(path.posix.normalize('../foo../../../bar'), '../../bar'); + assert.strictEqual(path.posix.normalize('../.../.././.../../../bar'), + '../../bar'); + assert.strictEqual(path.posix.normalize('../../../foo/../../../bar'), + '../../../../../bar'); + assert.strictEqual(path.posix.normalize('../../../foo/../../../bar/../../'), + '../../../../../../'); + assert.strictEqual( + path.posix.normalize('../foobar/barfoo/foo/../../../bar/../../'), + '../../' + ); + assert.strictEqual( + path.posix.normalize('../.../../foobar/../../../bar/../../baz'), + '../../../../baz' + ); + assert.strictEqual(path.posix.normalize('foo/bar\\baz'), 'foo/bar\\baz'); + }); + + test('isAbsolute', () => { + assert.strictEqual(path.win32.isAbsolute('/'), true); + assert.strictEqual(path.win32.isAbsolute('//'), true); + assert.strictEqual(path.win32.isAbsolute('//server'), true); + assert.strictEqual(path.win32.isAbsolute('//server/file'), true); + assert.strictEqual(path.win32.isAbsolute('\\\\server\\file'), true); + assert.strictEqual(path.win32.isAbsolute('\\\\server'), true); + assert.strictEqual(path.win32.isAbsolute('\\\\'), true); + assert.strictEqual(path.win32.isAbsolute('c'), false); + assert.strictEqual(path.win32.isAbsolute('c:'), false); + assert.strictEqual(path.win32.isAbsolute('c:\\'), true); + assert.strictEqual(path.win32.isAbsolute('c:/'), true); + assert.strictEqual(path.win32.isAbsolute('c://'), true); + assert.strictEqual(path.win32.isAbsolute('C:/Users/'), true); + assert.strictEqual(path.win32.isAbsolute('C:\\Users\\'), true); + assert.strictEqual(path.win32.isAbsolute('C:cwd/another'), false); + assert.strictEqual(path.win32.isAbsolute('C:cwd\\another'), false); + assert.strictEqual(path.win32.isAbsolute('directory/directory'), false); + assert.strictEqual(path.win32.isAbsolute('directory\\directory'), false); + + assert.strictEqual(path.posix.isAbsolute('/home/foo'), true); + assert.strictEqual(path.posix.isAbsolute('/home/foo/..'), true); + assert.strictEqual(path.posix.isAbsolute('bar/'), false); + assert.strictEqual(path.posix.isAbsolute('./baz'), false); + + // Tests from VSCode: + + // Absolute Paths + [ + 'C:/', + 'C:\\', + 'C:/foo', + 'C:\\foo', + 'z:/foo/bar.txt', + 'z:\\foo\\bar.txt', + + '\\\\localhost\\c$\\foo', + + '/', + '/foo' + ].forEach(absolutePath => { + assert.ok(path.win32.isAbsolute(absolutePath), absolutePath); + }); + + [ + '/', + '/foo', + '/foo/bar.txt' + ].forEach(absolutePath => { + assert.ok(path.posix.isAbsolute(absolutePath), absolutePath); + }); + + // Relative Paths + [ + '', + 'foo', + 'foo/bar', + './foo', + 'http://foo.com/bar' + ].forEach(nonAbsolutePath => { + assert.ok(!path.win32.isAbsolute(nonAbsolutePath), nonAbsolutePath); + }); + + [ + '', + 'foo', + 'foo/bar', + './foo', + 'http://foo.com/bar', + 'z:/foo/bar.txt', + ].forEach(nonAbsolutePath => { + assert.ok(!path.posix.isAbsolute(nonAbsolutePath), nonAbsolutePath); + }); + }); + + test('path', () => { + // path.sep tests + // windows + assert.strictEqual(path.win32.sep, '\\'); + // posix + assert.strictEqual(path.posix.sep, '/'); + + // path.delimiter tests + // windows + assert.strictEqual(path.win32.delimiter, ';'); + // posix + assert.strictEqual(path.posix.delimiter, ':'); + + // if (isWindows) { + // assert.strictEqual(path, path.win32); + // } else { + // assert.strictEqual(path, path.posix); + // } + }); + + // test('perf', () => { + // const folderNames = [ + // 'abc', + // 'Users', + // 'reallylongfoldername', + // 's', + // 'reallyreallyreallylongfoldername', + // 'home' + // ]; + + // const basePaths = [ + // 'C:', + // '', + // ]; + + // const separators = [ + // '\\', + // '/' + // ]; + + // function randomInt(ciel: number): number { + // return Math.floor(Math.random() * ciel); + // } + + // let pathsToNormalize = []; + // let pathsToJoin = []; + // let i; + // for (i = 0; i < 1000000; i++) { + // const basePath = basePaths[randomInt(basePaths.length)]; + // let lengthOfPath = randomInt(10) + 2; + + // let pathToNormalize = basePath + separators[randomInt(separators.length)]; + // while (lengthOfPath-- > 0) { + // pathToNormalize = pathToNormalize + folderNames[randomInt(folderNames.length)] + separators[randomInt(separators.length)]; + // } + + // pathsToNormalize.push(pathToNormalize); + + // let pathToJoin = ''; + // lengthOfPath = randomInt(10) + 2; + // while (lengthOfPath-- > 0) { + // pathToJoin = pathToJoin + folderNames[randomInt(folderNames.length)] + separators[randomInt(separators.length)]; + // } + + // pathsToJoin.push(pathToJoin + '.ts'); + // } + + // let newTime = 0; + + // let j; + // for(j = 0; j < pathsToJoin.length; j++) { + // const path1 = pathsToNormalize[j]; + // const path2 = pathsToNormalize[j]; + + // const newStart = performance.now(); + // path.join(path1, path2); + // newTime += performance.now() - newStart; + // } + + // assert.ok(false, `Time: ${newTime}ms.`); + // }); +}); diff --git a/src/vs/base/test/common/paths.test.ts b/src/vs/base/test/common/paths.test.ts deleted file mode 100644 index e0cf182e378..00000000000 --- a/src/vs/base/test/common/paths.test.ts +++ /dev/null @@ -1,228 +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 * as assert from 'assert'; -import * as paths from 'vs/base/common/paths'; -import * as platform from 'vs/base/common/platform'; - -suite('Paths', () => { - - test('dirname', () => { - assert.equal(paths.dirname('foo/bar'), 'foo'); - assert.equal(paths.dirname('foo\\bar'), 'foo'); - assert.equal(paths.dirname('/foo/bar'), '/foo'); - assert.equal(paths.dirname('\\foo\\bar'), '\\foo'); - assert.equal(paths.dirname('/foo'), '/'); - assert.equal(paths.dirname('\\foo'), '\\'); - assert.equal(paths.dirname('/'), '/'); - assert.equal(paths.dirname('\\'), '\\'); - assert.equal(paths.dirname('foo'), '.'); - assert.equal(paths.dirname('/folder/'), '/'); - if (platform.isWindows) { - assert.equal(paths.dirname('c:\\some\\file.txt'), 'c:\\some'); - assert.equal(paths.dirname('c:\\some'), 'c:\\'); - } - }); - - test('normalize', () => { - assert.equal(paths.normalize(''), '.'); - assert.equal(paths.normalize('.'), '.'); - assert.equal(paths.normalize('.'), '.'); - assert.equal(paths.normalize('../../far'), '../../far'); - assert.equal(paths.normalize('../bar'), '../bar'); - assert.equal(paths.normalize('../far'), '../far'); - assert.equal(paths.normalize('./'), './'); - assert.equal(paths.normalize('./././'), './'); - assert.equal(paths.normalize('./ff/./'), 'ff/'); - assert.equal(paths.normalize('./foo'), 'foo'); - assert.equal(paths.normalize('/'), '/'); - assert.equal(paths.normalize('/..'), '/'); - assert.equal(paths.normalize('///'), '/'); - assert.equal(paths.normalize('//foo'), '/foo'); - assert.equal(paths.normalize('//foo//'), '/foo/'); - assert.equal(paths.normalize('/foo'), '/foo'); - assert.equal(paths.normalize('/foo/bar.test'), '/foo/bar.test'); - assert.equal(paths.normalize('\\\\\\'), '/'); - assert.equal(paths.normalize('c:/../ff'), 'c:/ff'); - assert.equal(paths.normalize('c:\\./'), 'c:/'); - assert.equal(paths.normalize('foo/'), 'foo/'); - assert.equal(paths.normalize('foo/../../bar'), '../bar'); - assert.equal(paths.normalize('foo/./'), 'foo/'); - assert.equal(paths.normalize('foo/./bar'), 'foo/bar'); - assert.equal(paths.normalize('foo//'), 'foo/'); - assert.equal(paths.normalize('foo//'), 'foo/'); - assert.equal(paths.normalize('foo//bar'), 'foo/bar'); - assert.equal(paths.normalize('foo//bar/far'), 'foo/bar/far'); - assert.equal(paths.normalize('foo/bar/../../far'), 'far'); - assert.equal(paths.normalize('foo/bar/../far'), 'foo/far'); - assert.equal(paths.normalize('foo/far/../../bar'), 'bar'); - assert.equal(paths.normalize('foo/far/../../bar'), 'bar'); - assert.equal(paths.normalize('foo/xxx/..'), 'foo'); - assert.equal(paths.normalize('foo/xxx/../bar'), 'foo/bar'); - assert.equal(paths.normalize('foo/xxx/./..'), 'foo'); - assert.equal(paths.normalize('foo/xxx/./../bar'), 'foo/bar'); - assert.equal(paths.normalize('foo/xxx/./bar'), 'foo/xxx/bar'); - assert.equal(paths.normalize('foo\\bar'), 'foo/bar'); - assert.equal(paths.normalize(null), null); - assert.equal(paths.normalize(undefined), undefined); - - // https://github.com/Microsoft/vscode/issues/7234 - assert.equal(paths.join('/home/aeschli/workspaces/vscode/extensions/css', './syntaxes/css.plist'), '/home/aeschli/workspaces/vscode/extensions/css/syntaxes/css.plist'); - }); - - test('getRootLength', () => { - - assert.equal(paths.getRoot('/user/far'), '/'); - assert.equal(paths.getRoot('\\\\server\\share\\some\\path'), '//server/share/'); - assert.equal(paths.getRoot('//server/share/some/path'), '//server/share/'); - assert.equal(paths.getRoot('//server/share'), '/'); - assert.equal(paths.getRoot('//server'), '/'); - assert.equal(paths.getRoot('//server//'), '/'); - assert.equal(paths.getRoot('c:/user/far'), 'c:/'); - assert.equal(paths.getRoot('c:user/far'), 'c:'); - assert.equal(paths.getRoot('http://www'), ''); - assert.equal(paths.getRoot('http://www/'), 'http://www/'); - assert.equal(paths.getRoot('file:///foo'), 'file:///'); - assert.equal(paths.getRoot('file://foo'), ''); - - }); - - test('basename', () => { - assert.equal(paths.basename('foo/bar'), 'bar'); - assert.equal(paths.basename('foo\\bar'), 'bar'); - assert.equal(paths.basename('/foo/bar'), 'bar'); - assert.equal(paths.basename('\\foo\\bar'), 'bar'); - assert.equal(paths.basename('./bar'), 'bar'); - assert.equal(paths.basename('.\\bar'), 'bar'); - assert.equal(paths.basename('/bar'), 'bar'); - assert.equal(paths.basename('\\bar'), 'bar'); - assert.equal(paths.basename('bar/'), 'bar'); - assert.equal(paths.basename('bar\\'), 'bar'); - assert.equal(paths.basename('bar'), 'bar'); - assert.equal(paths.basename('////////'), ''); - assert.equal(paths.basename('\\\\\\\\'), ''); - }); - - test('join', () => { - assert.equal(paths.join('.', 'bar'), 'bar'); - assert.equal(paths.join('../../foo/bar', '../../foo'), '../../foo'); - assert.equal(paths.join('../../foo/bar', '../bar/foo'), '../../foo/bar/foo'); - assert.equal(paths.join('../foo/bar', '../bar/foo'), '../foo/bar/foo'); - assert.equal(paths.join('/', 'bar'), '/bar'); - assert.equal(paths.join('//server/far/boo', '../file.txt'), '//server/far/file.txt'); - assert.equal(paths.join('/foo/', '/bar'), '/foo/bar'); - assert.equal(paths.join('\\\\server\\far\\boo', '../file.txt'), '//server/far/file.txt'); - assert.equal(paths.join('\\\\server\\far\\boo', './file.txt'), '//server/far/boo/file.txt'); - assert.equal(paths.join('\\\\server\\far\\boo', '.\\file.txt'), '//server/far/boo/file.txt'); - assert.equal(paths.join('\\\\server\\far\\boo', 'file.txt'), '//server/far/boo/file.txt'); - assert.equal(paths.join('file:///c/users/test', 'test'), 'file:///c/users/test/test'); - assert.equal(paths.join('file://localhost/c$/GitDevelopment/express', './settings'), 'file://localhost/c$/GitDevelopment/express/settings'); // unc - assert.equal(paths.join('file://localhost/c$/GitDevelopment/express', '.settings'), 'file://localhost/c$/GitDevelopment/express/.settings'); // unc - assert.equal(paths.join('foo', '/bar'), 'foo/bar'); - assert.equal(paths.join('foo', 'bar'), 'foo/bar'); - assert.equal(paths.join('foo', 'bar/'), 'foo/bar/'); - assert.equal(paths.join('foo/', '/bar'), 'foo/bar'); - assert.equal(paths.join('foo/', '/bar/'), 'foo/bar/'); - assert.equal(paths.join('foo/', 'bar'), 'foo/bar'); - assert.equal(paths.join('foo/bar', '../bar/foo'), 'foo/bar/foo'); - assert.equal(paths.join('foo/bar', './bar/foo'), 'foo/bar/bar/foo'); - assert.equal(paths.join('http://localhost/test', '../next'), 'http://localhost/next'); - assert.equal(paths.join('http://localhost/test', 'test'), 'http://localhost/test/test'); - }); - - test('extname', () => { - assert.equal(paths.extname('far.boo'), '.boo'); - assert.equal(paths.extname('far.b'), '.b'); - assert.equal(paths.extname('far.'), '.'); - assert.equal(paths.extname('far.boo/boo.far'), '.far'); - assert.equal(paths.extname('far.boo/boo'), ''); - }); - - test('isUNC', () => { - if (platform.isWindows) { - assert.ok(!paths.isUNC('foo')); - assert.ok(!paths.isUNC('/foo')); - assert.ok(!paths.isUNC('\\foo')); - assert.ok(!paths.isUNC('\\\\foo')); - assert.ok(paths.isUNC('\\\\a\\b')); - assert.ok(!paths.isUNC('//a/b')); - assert.ok(paths.isUNC('\\\\server\\share')); - assert.ok(paths.isUNC('\\\\server\\share\\')); - assert.ok(paths.isUNC('\\\\server\\share\\path')); - } - }); - - test('isValidBasename', () => { - assert.ok(!paths.isValidBasename(null)); - assert.ok(!paths.isValidBasename('')); - assert.ok(paths.isValidBasename('test.txt')); - assert.ok(!paths.isValidBasename('/test.txt')); - assert.ok(!paths.isValidBasename('\\test.txt')); - - if (platform.isWindows) { - assert.ok(!paths.isValidBasename('aux')); - assert.ok(!paths.isValidBasename('Aux')); - assert.ok(!paths.isValidBasename('LPT0')); - assert.ok(!paths.isValidBasename('test.txt.')); - assert.ok(!paths.isValidBasename('test.txt..')); - assert.ok(!paths.isValidBasename('test.txt ')); - assert.ok(!paths.isValidBasename('test.txt\t')); - assert.ok(!paths.isValidBasename('tes:t.txt')); - assert.ok(!paths.isValidBasename('tes"t.txt')); - } - }); - - test('isAbsolute_win', () => { - // Absolute paths - [ - 'C:/', - 'C:\\', - 'C:/foo', - 'C:\\foo', - 'z:/foo/bar.txt', - 'z:\\foo\\bar.txt', - - '\\\\localhost\\c$\\foo', - - '/', - '/foo' - ].forEach(absolutePath => { - assert.ok(paths.isAbsolute_win32(absolutePath), absolutePath); - }); - - // Not absolute paths - [ - '', - 'foo', - 'foo/bar', - './foo', - 'http://foo.com/bar' - ].forEach(nonAbsolutePath => { - assert.ok(!paths.isAbsolute_win32(nonAbsolutePath), nonAbsolutePath); - }); - }); - - test('isAbsolute_posix', () => { - // Absolute paths - [ - '/', - '/foo', - '/foo/bar.txt' - ].forEach(absolutePath => { - assert.ok(paths.isAbsolute_posix(absolutePath), absolutePath); - }); - - // Not absolute paths - [ - '', - 'foo', - 'foo/bar', - './foo', - 'http://foo.com/bar', - 'z:/foo/bar.txt', - ].forEach(nonAbsolutePath => { - assert.ok(!paths.isAbsolute_posix(nonAbsolutePath), nonAbsolutePath); - }); - }); -}); diff --git a/src/vs/base/test/common/processes.test.ts b/src/vs/base/test/common/processes.test.ts new file mode 100644 index 00000000000..cd54b6fd724 --- /dev/null +++ b/src/vs/base/test/common/processes.test.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import * as processes from 'vs/base/common/processes'; + +suite('Processes', () => { + test('sanitizeProcessEnvironment', () => { + let env = { + FOO: 'bar', + ELECTRON_ENABLE_STACK_DUMPING: 'x', + ELECTRON_ENABLE_LOGGING: 'x', + ELECTRON_NO_ASAR: 'x', + ELECTRON_NO_ATTACH_CONSOLE: 'x', + ELECTRON_RUN_AS_NODE: 'x', + GOOGLE_API_KEY: 'x', + VSCODE_CLI: 'x', + VSCODE_DEV: 'x', + VSCODE_IPC_HOOK: 'x', + VSCODE_LOGS: 'x', + VSCODE_NLS_CONFIG: 'x', + VSCODE_PORTABLE: 'x', + VSCODE_PID: 'x', + VSCODE_NODE_CACHED_DATA_DIR: 'x', + VSCODE_NEW_VAR: 'x' + }; + processes.sanitizeProcessEnvironment(env); + assert.equal(env['FOO'], 'bar'); + assert.equal(Object.keys(env).length, 1); + }); +}); diff --git a/src/vs/base/test/common/resources.test.ts b/src/vs/base/test/common/resources.test.ts index 919855add12..cb535362222 100644 --- a/src/vs/base/test/common/resources.test.ts +++ b/src/vs/base/test/common/resources.test.ts @@ -3,9 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { dirname, basename, distinctParents, joinPath, isEqual, isEqualOrParent, hasToIgnoreCase, normalizePath, isAbsolutePath, isMalformedFileUri } from 'vs/base/common/resources'; -import { URI, setUriThrowOnMissingScheme } from 'vs/base/common/uri'; +import { dirname, basename, distinctParents, joinPath, isEqual, isEqualOrParent, hasToIgnoreCase, normalizePath, isAbsolutePath, relativePath, removeTrailingPathSeparator, hasTrailingPathSeparator, resolvePath, addTrailingPathSeparator } from 'vs/base/common/resources'; +import { URI } from 'vs/base/common/uri'; import { isWindows } from 'vs/base/common/platform'; +import { toSlashes } from 'vs/base/common/extpath'; +import { startsWith } from 'vs/base/common/strings'; +import { isAbsolute } from 'vs/base/common/path'; + suite('Resources', () => { @@ -42,20 +46,23 @@ suite('Resources', () => { test('dirname', () => { if (isWindows) { - assert.equal(dirname(URI.file('c:\\some\\file\\test.txt'))!.toString(), 'file:///c%3A/some/file'); - assert.equal(dirname(URI.file('c:\\some\\file'))!.toString(), 'file:///c%3A/some'); - assert.equal(dirname(URI.file('c:\\some\\file\\'))!.toString(), 'file:///c%3A/some'); - assert.equal(dirname(URI.file('c:\\some'))!.toString(), 'file:///c%3A/'); - assert.equal(dirname(URI.file('C:\\some'))!.toString(), 'file:///c%3A/'); + assert.equal(dirname(URI.file('c:\\some\\file\\test.txt')).toString(), 'file:///c%3A/some/file'); + assert.equal(dirname(URI.file('c:\\some\\file')).toString(), 'file:///c%3A/some'); + assert.equal(dirname(URI.file('c:\\some\\file\\')).toString(), 'file:///c%3A/some'); + assert.equal(dirname(URI.file('c:\\some')).toString(), 'file:///c%3A/'); + assert.equal(dirname(URI.file('C:\\some')).toString(), 'file:///c%3A/'); + assert.equal(dirname(URI.file('c:\\')).toString(), 'file:///c%3A/'); } else { - assert.equal(dirname(URI.file('/some/file/test.txt'))!.toString(), 'file:///some/file'); - assert.equal(dirname(URI.file('/some/file/'))!.toString(), 'file:///some'); - assert.equal(dirname(URI.file('/some/file'))!.toString(), 'file:///some'); + assert.equal(dirname(URI.file('/some/file/test.txt')).toString(), 'file:///some/file'); + assert.equal(dirname(URI.file('/some/file/')).toString(), 'file:///some'); + assert.equal(dirname(URI.file('/some/file')).toString(), 'file:///some'); } - assert.equal(dirname(URI.parse('foo://a/some/file/test.txt'))!.toString(), 'foo://a/some/file'); - assert.equal(dirname(URI.parse('foo://a/some/file/'))!.toString(), 'foo://a/some'); - assert.equal(dirname(URI.parse('foo://a/some/file'))!.toString(), 'foo://a/some'); - assert.equal(dirname(URI.parse('foo://a/some'))!.toString(), 'foo://a/'); + assert.equal(dirname(URI.parse('foo://a/some/file/test.txt')).toString(), 'foo://a/some/file'); + assert.equal(dirname(URI.parse('foo://a/some/file/')).toString(), 'foo://a/some'); + assert.equal(dirname(URI.parse('foo://a/some/file')).toString(), 'foo://a/some'); + assert.equal(dirname(URI.parse('foo://a/some')).toString(), 'foo://a/'); + assert.equal(dirname(URI.parse('foo://a/')).toString(), 'foo://a/'); + assert.equal(dirname(URI.parse('foo://a')).toString(), 'foo://a'); // does not explode (https://github.com/Microsoft/vscode/issues/41987) dirname(URI.from({ scheme: 'file', authority: '/users/someone/portal.h' })); @@ -135,6 +142,7 @@ suite('Resources', () => { assert.equal(normalizePath(URI.file('/foo/foo/../../bar')).toString(), 'file:///bar'); assert.equal(normalizePath(URI.file('/foo/foo/./../../bar')).toString(), 'file:///bar'); assert.equal(normalizePath(URI.file('/foo/foo/./../some/../bar')).toString(), 'file:///foo/bar'); + assert.equal(normalizePath(URI.file('/f')).toString(), 'file:///f'); } assert.equal(normalizePath(URI.parse('foo://a/foo/./bar')).toString(), 'foo://a/foo/bar'); assert.equal(normalizePath(URI.parse('foo://a/foo/.')).toString(), 'foo://a/foo'); @@ -145,6 +153,8 @@ suite('Resources', () => { assert.equal(normalizePath(URI.parse('foo://a/foo/foo/../../bar')).toString(), 'foo://a/bar'); assert.equal(normalizePath(URI.parse('foo://a/foo/foo/./../../bar')).toString(), 'foo://a/bar'); assert.equal(normalizePath(URI.parse('foo://a/foo/foo/./../some/../bar')).toString(), 'foo://a/foo/bar'); + assert.equal(normalizePath(URI.parse('foo://a')).toString(), 'foo://a'); + assert.equal(normalizePath(URI.parse('foo://a/')).toString(), 'foo://a/'); }); test('isAbsolute', () => { @@ -160,6 +170,173 @@ suite('Resources', () => { assert.equal(isAbsolutePath(URI.parse('foo://a/foo/.')), true); }); + function assertTrailingSeparator(u1: URI, expected: boolean) { + assert.equal(hasTrailingPathSeparator(u1), expected, u1.toString()); + } + + function assertRemoveTrailingSeparator(u1: URI, expected: URI) { + assertEqualURI(removeTrailingPathSeparator(u1), expected, u1.toString()); + } + + function assertAddTrailingSeparator(u1: URI, expected: URI) { + assertEqualURI(addTrailingPathSeparator(u1), expected, u1.toString()); + } + + test('trailingPathSeparator', () => { + assertTrailingSeparator(URI.parse('foo://a/foo'), false); + assertTrailingSeparator(URI.parse('foo://a/foo/'), true); + assertTrailingSeparator(URI.parse('foo://a/'), false); + assertTrailingSeparator(URI.parse('foo://a'), false); + + assertRemoveTrailingSeparator(URI.parse('foo://a/foo'), URI.parse('foo://a/foo')); + assertRemoveTrailingSeparator(URI.parse('foo://a/foo/'), URI.parse('foo://a/foo')); + assertRemoveTrailingSeparator(URI.parse('foo://a/'), URI.parse('foo://a/')); + assertRemoveTrailingSeparator(URI.parse('foo://a'), URI.parse('foo://a')); + + assertAddTrailingSeparator(URI.parse('foo://a/foo'), URI.parse('foo://a/foo/')); + assertAddTrailingSeparator(URI.parse('foo://a/foo/'), URI.parse('foo://a/foo/')); + assertAddTrailingSeparator(URI.parse('foo://a/'), URI.parse('foo://a/')); + assertAddTrailingSeparator(URI.parse('foo://a'), URI.parse('foo://a/')); + + if (isWindows) { + assertTrailingSeparator(URI.file('c:\\a\\foo'), false); + assertTrailingSeparator(URI.file('c:\\a\\foo\\'), true); + assertTrailingSeparator(URI.file('c:\\'), false); + assertTrailingSeparator(URI.file('\\\\server\\share\\some\\'), true); + assertTrailingSeparator(URI.file('\\\\server\\share\\'), false); + + assertRemoveTrailingSeparator(URI.file('c:\\a\\foo'), URI.file('c:\\a\\foo')); + assertRemoveTrailingSeparator(URI.file('c:\\a\\foo\\'), URI.file('c:\\a\\foo')); + assertRemoveTrailingSeparator(URI.file('c:\\'), URI.file('c:\\')); + assertRemoveTrailingSeparator(URI.file('\\\\server\\share\\some\\'), URI.file('\\\\server\\share\\some')); + assertRemoveTrailingSeparator(URI.file('\\\\server\\share\\'), URI.file('\\\\server\\share\\')); + + assertAddTrailingSeparator(URI.file('c:\\a\\foo'), URI.file('c:\\a\\foo\\')); + assertAddTrailingSeparator(URI.file('c:\\a\\foo\\'), URI.file('c:\\a\\foo\\')); + assertAddTrailingSeparator(URI.file('c:\\'), URI.file('c:\\')); + assertAddTrailingSeparator(URI.file('\\\\server\\share\\some'), URI.file('\\\\server\\share\\some\\')); + assertAddTrailingSeparator(URI.file('\\\\server\\share\\some\\'), URI.file('\\\\server\\share\\some\\')); + } else { + assertTrailingSeparator(URI.file('/foo/bar'), false); + assertTrailingSeparator(URI.file('/foo/bar/'), true); + assertTrailingSeparator(URI.file('/'), false); + + assertRemoveTrailingSeparator(URI.file('/foo/bar'), URI.file('/foo/bar')); + assertRemoveTrailingSeparator(URI.file('/foo/bar/'), URI.file('/foo/bar')); + assertRemoveTrailingSeparator(URI.file('/'), URI.file('/')); + + assertAddTrailingSeparator(URI.file('/foo/bar'), URI.file('/foo/bar/')); + assertAddTrailingSeparator(URI.file('/foo/bar/'), URI.file('/foo/bar/')); + assertAddTrailingSeparator(URI.file('/'), URI.file('/')); + } + }); + + function assertEqualURI(actual: URI, expected: URI, message?: string) { + if (!isEqual(expected, actual)) { + assert.equal(actual.toString(), expected.toString(), message); + } + } + + function assertRelativePath(u1: URI, u2: URI, expectedPath: string | undefined, ignoreJoin?: boolean, ignoreCase?: boolean) { + assert.equal(relativePath(u1, u2, ignoreCase), expectedPath, `from ${u1.toString()} to ${u2.toString()}`); + if (expectedPath !== undefined && !ignoreJoin) { + assertEqualURI(removeTrailingPathSeparator(joinPath(u1, expectedPath)), removeTrailingPathSeparator(u2), 'joinPath on relativePath should be equal'); + } + } + + test('relativePath', () => { + assertRelativePath(URI.parse('foo://a/foo'), URI.parse('foo://a/foo/bar'), 'bar'); + assertRelativePath(URI.parse('foo://a/foo'), URI.parse('foo://a/foo/bar/'), 'bar'); + assertRelativePath(URI.parse('foo://a/foo'), URI.parse('foo://a/foo/bar/goo'), 'bar/goo'); + assertRelativePath(URI.parse('foo://a/'), URI.parse('foo://a/foo/bar/goo'), 'foo/bar/goo'); + assertRelativePath(URI.parse('foo://a/foo/xoo'), URI.parse('foo://a/foo/bar'), '../bar'); + assertRelativePath(URI.parse('foo://a/foo/xoo/yoo'), URI.parse('foo://a'), '../../..'); + assertRelativePath(URI.parse('foo://a/foo'), URI.parse('foo://a/foo/'), ''); + assertRelativePath(URI.parse('foo://a/foo/'), URI.parse('foo://a/foo'), ''); + assertRelativePath(URI.parse('foo://a/foo/'), URI.parse('foo://a/foo/'), ''); + assertRelativePath(URI.parse('foo://a/foo'), URI.parse('foo://a/foo'), ''); + assertRelativePath(URI.parse('foo://a'), URI.parse('foo://a'), ''); + assertRelativePath(URI.parse('foo://a/'), URI.parse('foo://a/'), ''); + assertRelativePath(URI.parse('foo://a/'), URI.parse('foo://a'), ''); + assertRelativePath(URI.parse('foo://a/foo?q'), URI.parse('foo://a/foo/bar#h'), 'bar'); + assertRelativePath(URI.parse('foo://'), URI.parse('foo://a/b'), undefined); + assertRelativePath(URI.parse('foo://a2/b'), URI.parse('foo://a/b'), undefined); + assertRelativePath(URI.parse('goo://a/b'), URI.parse('foo://a/b'), undefined); + + assertRelativePath(URI.parse('foo://a/foo'), URI.parse('foo://A/FOO/bar/goo'), 'bar/goo', false, true); + assertRelativePath(URI.parse('foo://a/foo'), URI.parse('foo://A/FOO/BAR/GOO'), 'BAR/GOO', false, true); + assertRelativePath(URI.parse('foo://a/foo/xoo'), URI.parse('foo://A/FOO/BAR/GOO'), '../BAR/GOO', false, true); + assertRelativePath(URI.parse('foo:///c:/a/foo'), URI.parse('foo:///C:/a/foo/xoo/'), 'xoo', false, true); + + if (isWindows) { + assertRelativePath(URI.file('c:\\foo\\bar'), URI.file('c:\\foo\\bar'), ''); + assertRelativePath(URI.file('c:\\foo\\bar\\huu'), URI.file('c:\\foo\\bar'), '..'); + assertRelativePath(URI.file('c:\\foo\\bar\\a1\\a2'), URI.file('c:\\foo\\bar'), '../..'); + assertRelativePath(URI.file('c:\\foo\\bar\\'), URI.file('c:\\foo\\bar\\a1\\a2'), 'a1/a2'); + assertRelativePath(URI.file('c:\\foo\\bar\\'), URI.file('c:\\foo\\bar\\a1\\a2\\'), 'a1/a2'); + assertRelativePath(URI.file('c:\\'), URI.file('c:\\foo\\bar'), 'foo/bar'); + assertRelativePath(URI.file('\\\\server\\share\\some\\'), URI.file('\\\\server\\share\\some\\path'), 'path'); + assertRelativePath(URI.file('\\\\server\\share\\some\\'), URI.file('\\\\server\\share2\\some\\path'), '../../share2/some/path', true); // ignore joinPath assert: path.join is not root aware + } else { + assertRelativePath(URI.file('/a/foo'), URI.file('/a/foo/bar'), 'bar'); + assertRelativePath(URI.file('/a/foo'), URI.file('/a/foo/bar/'), 'bar'); + assertRelativePath(URI.file('/a/foo'), URI.file('/a/foo/bar/goo'), 'bar/goo'); + assertRelativePath(URI.file('/a/'), URI.file('/a/foo/bar/goo'), 'foo/bar/goo'); + assertRelativePath(URI.file('/'), URI.file('/a/foo/bar/goo'), 'a/foo/bar/goo'); + assertRelativePath(URI.file('/a/foo/xoo'), URI.file('/a/foo/bar'), '../bar'); + assertRelativePath(URI.file('/a/foo/xoo/yoo'), URI.file('/a'), '../../..'); + assertRelativePath(URI.file('/a/foo'), URI.file('/a/foo/'), ''); + assertRelativePath(URI.file('/a/foo'), URI.file('/b/foo/'), '../../b/foo'); + } + }); + + function assertResolve(u1: URI, path: string, expected: URI) { + const actual = resolvePath(u1, path); + assertEqualURI(actual, expected, `from ${u1.toString()} and ${path}`); + + if (!isAbsolute(path)) { + let expectedPath = isWindows ? toSlashes(path) : path; + expectedPath = startsWith(expectedPath, './') ? expectedPath.substr(2) : expectedPath; + assert.equal(relativePath(u1, actual), expectedPath, `relativePath (${u1.toString()}) on actual (${actual.toString()}) should be to path (${expectedPath})`); + } + } + + test('resolve', () => { + if (isWindows) { + assertResolve(URI.file('c:\\foo\\bar'), 'file.js', URI.file('c:\\foo\\bar\\file.js')); + assertResolve(URI.file('c:\\foo\\bar'), 't\\file.js', URI.file('c:\\foo\\bar\\t\\file.js')); + assertResolve(URI.file('c:\\foo\\bar'), '.\\t\\file.js', URI.file('c:\\foo\\bar\\t\\file.js')); + assertResolve(URI.file('c:\\foo\\bar'), 'a1/file.js', URI.file('c:\\foo\\bar\\a1\\file.js')); + assertResolve(URI.file('c:\\foo\\bar'), './a1/file.js', URI.file('c:\\foo\\bar\\a1\\file.js')); + assertResolve(URI.file('c:\\foo\\bar'), '\\b1\\file.js', URI.file('c:\\b1\\file.js')); + assertResolve(URI.file('c:\\foo\\bar'), '/b1/file.js', URI.file('c:\\b1\\file.js')); + assertResolve(URI.file('c:\\foo\\bar\\'), 'file.js', URI.file('c:\\foo\\bar\\file.js')); + + assertResolve(URI.file('c:\\'), 'file.js', URI.file('c:\\file.js')); + assertResolve(URI.file('c:\\'), '\\b1\\file.js', URI.file('c:\\b1\\file.js')); + assertResolve(URI.file('c:\\'), '/b1/file.js', URI.file('c:\\b1\\file.js')); + assertResolve(URI.file('c:\\'), 'd:\\foo\\bar.txt', URI.file('d:\\foo\\bar.txt')); + + assertResolve(URI.file('\\\\server\\share\\some\\'), 'b1\\file.js', URI.file('\\\\server\\share\\some\\b1\\file.js')); + assertResolve(URI.file('\\\\server\\share\\some\\'), '\\file.js', URI.file('\\\\server\\share\\file.js')); + + assertResolve(URI.file('c:\\'), '\\\\server\\share\\some\\', URI.file('\\\\server\\share\\some')); + assertResolve(URI.file('\\\\server\\share\\some\\'), 'c:\\', URI.file('c:\\')); + } else { + assertResolve(URI.file('/foo/bar'), 'file.js', URI.file('/foo/bar/file.js')); + assertResolve(URI.file('/foo/bar'), './file.js', URI.file('/foo/bar/file.js')); + assertResolve(URI.file('/foo/bar'), '/file.js', URI.file('/file.js')); + assertResolve(URI.file('/foo/bar/'), 'file.js', URI.file('/foo/bar/file.js')); + assertResolve(URI.file('/'), 'file.js', URI.file('/file.js')); + assertResolve(URI.file(''), './file.js', URI.file('/file.js')); + assertResolve(URI.file(''), '/file.js', URI.file('/file.js')); + } + + assertResolve(URI.parse('foo://server/foo/bar'), 'file.js', URI.parse('foo://server/foo/bar/file.js')); + assertResolve(URI.parse('foo://server/foo/bar'), './file.js', URI.parse('foo://server/foo/bar/file.js')); + assertResolve(URI.parse('foo://server/foo/bar'), './file.js', URI.parse('foo://server/foo/bar/file.js')); + }); + test('isEqual', () => { let fileURI = isWindows ? URI.file('c:\\foo\\bar') : URI.file('/foo/bar'); let fileURI2 = isWindows ? URI.file('C:\\foo\\Bar') : URI.file('/foo/Bar'); @@ -178,6 +355,8 @@ suite('Resources', () => { assert.equal(isEqual(fileURI3, fileURI4, false), false); assert.equal(isEqual(fileURI, fileURI3, true), false); + + assert.equal(isEqual(URI.parse('foo://server'), URI.parse('foo://server/')), true); }); test('isEqualOrParent', () => { @@ -204,27 +383,4 @@ suite('Resources', () => { assert.equal(isEqualOrParent(fileURI3, fileURI, true), false, '15'); assert.equal(isEqualOrParent(fileURI5, fileURI5, true), true, '16'); }); - - function assertMalformedFileUri(path: string, expected: string | undefined) { - const old = setUriThrowOnMissingScheme(false); - const newURI = isMalformedFileUri(URI.parse(path)); - assert.equal(newURI && newURI.toString(), expected); - setUriThrowOnMissingScheme(old); - } - - test('isMalformedFileUri', () => { - if (isWindows) { - assertMalformedFileUri('c:/foo/bar', 'file:///c%3A/foo/bar'); - assertMalformedFileUri('c:\\foo\\bar', 'file:///c%3A/foo/bar'); - assertMalformedFileUri('C:\\foo\\bar', 'file:///c%3A/foo/bar'); - assertMalformedFileUri('\\\\localhost\\c$\\devel\\test', 'file://localhost/c%24/devel/test'); - } - assertMalformedFileUri('/foo/bar', 'file:///foo/bar'); - - assertMalformedFileUri('file:///foo/bar', undefined); - assertMalformedFileUri('file:///c%3A/foo/bar', undefined); - assertMalformedFileUri('file://localhost/c$/devel/test', undefined); - assertMalformedFileUri('foo://dadie/foo/bar', undefined); - assertMalformedFileUri('foo:///dadie/foo/bar', undefined); - }); }); diff --git a/src/vs/base/test/common/strings.test.ts b/src/vs/base/test/common/strings.test.ts index 758bfb246d1..015075a90a9 100644 --- a/src/vs/base/test/common/strings.test.ts +++ b/src/vs/base/test/common/strings.test.ts @@ -403,4 +403,59 @@ suite('Strings', () => { assert.equal(strings.getNLines('foo\nbar\nsomething', 2), 'foo\nbar'); assert.equal(strings.getNLines('foo', 0), ''); }); + + test('removeAccents', function () { + assert.equal(strings.removeAccents('joào'), 'joao'); + assert.equal(strings.removeAccents('joáo'), 'joao'); + assert.equal(strings.removeAccents('joâo'), 'joao'); + assert.equal(strings.removeAccents('joäo'), 'joao'); + // assert.equal(strings.removeAccents('joæo'), 'joao'); // not an accent + assert.equal(strings.removeAccents('joão'), 'joao'); + assert.equal(strings.removeAccents('joåo'), 'joao'); + assert.equal(strings.removeAccents('joåo'), 'joao'); + assert.equal(strings.removeAccents('joāo'), 'joao'); + + assert.equal(strings.removeAccents('fôo'), 'foo'); + assert.equal(strings.removeAccents('föo'), 'foo'); + assert.equal(strings.removeAccents('fòo'), 'foo'); + assert.equal(strings.removeAccents('fóo'), 'foo'); + // assert.equal(strings.removeAccents('fœo'), 'foo'); + // assert.equal(strings.removeAccents('føo'), 'foo'); + assert.equal(strings.removeAccents('fōo'), 'foo'); + assert.equal(strings.removeAccents('fõo'), 'foo'); + + assert.equal(strings.removeAccents('andrè'), 'andre'); + assert.equal(strings.removeAccents('andré'), 'andre'); + assert.equal(strings.removeAccents('andrê'), 'andre'); + assert.equal(strings.removeAccents('andrë'), 'andre'); + assert.equal(strings.removeAccents('andrē'), 'andre'); + assert.equal(strings.removeAccents('andrė'), 'andre'); + assert.equal(strings.removeAccents('andrę'), 'andre'); + + assert.equal(strings.removeAccents('hvîc'), 'hvic'); + assert.equal(strings.removeAccents('hvïc'), 'hvic'); + assert.equal(strings.removeAccents('hvíc'), 'hvic'); + assert.equal(strings.removeAccents('hvīc'), 'hvic'); + assert.equal(strings.removeAccents('hvįc'), 'hvic'); + assert.equal(strings.removeAccents('hvìc'), 'hvic'); + + assert.equal(strings.removeAccents('ûdo'), 'udo'); + assert.equal(strings.removeAccents('üdo'), 'udo'); + assert.equal(strings.removeAccents('ùdo'), 'udo'); + assert.equal(strings.removeAccents('údo'), 'udo'); + assert.equal(strings.removeAccents('ūdo'), 'udo'); + + assert.equal(strings.removeAccents('heÿ'), 'hey'); + + // assert.equal(strings.removeAccents('gruß'), 'grus'); + assert.equal(strings.removeAccents('gruś'), 'grus'); + assert.equal(strings.removeAccents('gruš'), 'grus'); + + assert.equal(strings.removeAccents('çool'), 'cool'); + assert.equal(strings.removeAccents('ćool'), 'cool'); + assert.equal(strings.removeAccents('čool'), 'cool'); + + assert.equal(strings.removeAccents('ñice'), 'nice'); + assert.equal(strings.removeAccents('ńice'), 'nice'); + }); }); diff --git a/src/vs/base/test/common/types.test.ts b/src/vs/base/test/common/types.test.ts index 27927725a27..43241b9a9c2 100644 --- a/src/vs/base/test/common/types.test.ts +++ b/src/vs/base/test/common/types.test.ts @@ -176,42 +176,17 @@ suite('Types', () => { types.validateConstraints([undefined], [types.isUndefined]); types.validateConstraints([1], [types.isNumber]); - function foo() { } - types.validateConstraints([new foo()], [foo]); + class Foo { } + types.validateConstraints([new Foo()], [Foo]); - function isFoo(f) { } - assert.throws(() => types.validateConstraints([new foo()], [isFoo])); + function isFoo(f: any) { } + assert.throws(() => types.validateConstraints([new Foo()], [isFoo])); - function isFoo2(f) { return true; } - types.validateConstraints([new foo()], [isFoo2]); + function isFoo2(f: any) { return true; } + types.validateConstraints([new Foo()], [isFoo2]); assert.throws(() => types.validateConstraints([1, true], [types.isNumber, types.isString])); assert.throws(() => types.validateConstraints(['2'], [types.isNumber])); assert.throws(() => types.validateConstraints([1, 'test', true], [Number, String, Number])); }); - - test('create', () => { - let zeroConstructor = function () { /**/ }; - - assert(types.create(zeroConstructor) instanceof zeroConstructor); - assert(types.isObject(types.create(zeroConstructor))); - - let manyArgConstructor = function (this: any, foo, bar) { - this.foo = foo; - this.bar = bar; - }; - - let foo = {}; - let bar = 'foo'; - - assert(types.create(manyArgConstructor) instanceof manyArgConstructor); - assert(types.isObject(types.create(manyArgConstructor))); - - assert(types.create(manyArgConstructor, foo, bar) instanceof manyArgConstructor); - assert(types.isObject(types.create(manyArgConstructor, foo, bar))); - - let obj = types.create(manyArgConstructor, foo, bar); - assert.strictEqual(obj.foo, foo); - assert.strictEqual(obj.bar, bar); - }); -}); \ No newline at end of file +}); diff --git a/src/vs/base/test/common/uri.test.ts b/src/vs/base/test/common/uri.test.ts index 038c475fd1d..0a72ec39876 100644 --- a/src/vs/base/test/common/uri.test.ts +++ b/src/vs/base/test/common/uri.test.ts @@ -3,8 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { URI } from 'vs/base/common/uri'; -import { normalize } from 'vs/base/common/paths'; +import { URI, UriComponents } from 'vs/base/common/uri'; import { isWindows } from 'vs/base/common/platform'; @@ -141,7 +140,6 @@ suite('URI', () => { assert.equal(value.scheme, 'http'); assert.equal(value.authority, 'api'); assert.equal(value.path, '/files/test.me'); - assert.equal(value.fsPath, normalize('/files/test.me', true)); assert.equal(value.query, 't=1234'); assert.equal(value.fragment, ''); @@ -151,7 +149,7 @@ suite('URI', () => { assert.equal(value.path, '/c:/test/me'); assert.equal(value.fragment, ''); assert.equal(value.query, ''); - assert.equal(value.fsPath, normalize('c:/test/me', true)); + assert.equal(value.fsPath, isWindows ? 'c:\\test\\me' : 'c:/test/me'); value = URI.parse('file://shares/files/c%23/p.cs'); assert.equal(value.scheme, 'file'); @@ -159,7 +157,7 @@ suite('URI', () => { assert.equal(value.path, '/files/c#/p.cs'); assert.equal(value.fragment, ''); assert.equal(value.query, ''); - assert.equal(value.fsPath, normalize('//shares/files/c#/p.cs', true)); + assert.equal(value.fsPath, isWindows ? '\\\\shares\\files\\c#\\p.cs' : '//shares/files/c#/p.cs'); value = URI.parse('file:///c:/Source/Z%C3%BCrich%20or%20Zurich%20(%CB%88zj%CA%8A%C9%99r%C9%AAk,/Code/resources/app/plugins/c%23/plugin.json'); assert.equal(value.scheme, 'file'); @@ -360,7 +358,6 @@ suite('URI', () => { test('correctFileUriToFilePath2', () => { const test = (input: string, expected: string) => { - expected = normalize(expected, true); const value = URI.parse(input); assert.equal(value.fsPath, expected, 'Result for ' + input); const value2 = URI.file(value.fsPath); @@ -368,10 +365,10 @@ suite('URI', () => { assert.equal(value.toString(), value2.toString()); }; - test('file:///c:/alex.txt', 'c:\\alex.txt'); - test('file:///c:/Source/Z%C3%BCrich%20or%20Zurich%20(%CB%88zj%CA%8A%C9%99r%C9%AAk,/Code/resources/app/plugins', 'c:\\Source\\Zürich or Zurich (ˈzjʊərɪk,\\Code\\resources\\app\\plugins'); - test('file://monacotools/folder/isi.txt', '\\\\monacotools\\folder\\isi.txt'); - test('file://monacotools1/certificates/SSL/', '\\\\monacotools1\\certificates\\SSL\\'); + test('file:///c:/alex.txt', isWindows ? 'c:\\alex.txt' : 'c:/alex.txt'); + test('file:///c:/Source/Z%C3%BCrich%20or%20Zurich%20(%CB%88zj%CA%8A%C9%99r%C9%AAk,/Code/resources/app/plugins', isWindows ? 'c:\\Source\\Zürich or Zurich (ˈzjʊərɪk,\\Code\\resources\\app\\plugins' : 'c:/Source/Zürich or Zurich (ˈzjʊərɪk,/Code/resources/app/plugins'); + test('file://monacotools/folder/isi.txt', isWindows ? '\\\\monacotools\\folder\\isi.txt' : '//monacotools/folder/isi.txt'); + test('file://monacotools1/certificates/SSL/', isWindows ? '\\\\monacotools1\\certificates\\SSL\\' : '//monacotools1/certificates/SSL/'); }); test('URI - http, query & toString', function () { @@ -429,6 +426,19 @@ suite('URI', () => { assert.equal(uri.toString(true), input); }); + test('Unable to open \'%A0.txt\': URI malformed #76506', function () { + + let uri = URI.file('/foo/%A0.txt'); + let uri2 = URI.parse(uri.toString()); + assert.equal(uri.scheme, uri2.scheme); + assert.equal(uri.path, uri2.path); + + uri = URI.file('/foo/%2e.txt'); + uri2 = URI.parse(uri.toString()); + assert.equal(uri.scheme, uri2.scheme); + assert.equal(uri.path, uri2.path); + }); + test('URI - (de)serialize', function () { const values = [ @@ -444,7 +454,7 @@ suite('URI', () => { // let c = 100000; // while (c-- > 0) { for (let value of values) { - let data = value.toJSON(); + let data = value.toJSON() as UriComponents; let clone = URI.revive(data); assert.equal(clone.scheme, value.scheme); diff --git a/src/vs/base/test/common/utils.ts b/src/vs/base/test/common/utils.ts index 63e4393926b..26b225a1fa9 100644 --- a/src/vs/base/test/common/utils.ts +++ b/src/vs/base/test/common/utils.ts @@ -3,16 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as paths from 'vs/base/common/paths'; +import { join } from 'vs/base/common/path'; import { URI } from 'vs/base/common/uri'; import { canceled } from 'vs/base/common/errors'; +import { isWindows } from 'vs/base/common/platform'; export type ValueCallback = (value: T | Promise) => void; export class DeferredPromise { - private completeCallback: ValueCallback; - private errorCallback: (err: any) => void; + private completeCallback!: ValueCallback; + private errorCallback!: (err: any) => void; public p: Promise; @@ -49,7 +50,11 @@ export class DeferredPromise { } export function toResource(this: any, path: string) { - return URI.file(paths.join('C:\\', Buffer.from(this.test.fullTitle()).toString('base64'), path)); + if (isWindows) { + return URI.file(join('C:\\', Buffer.from(this.test.fullTitle()).toString('base64'), path)); + } + + return URI.file(join('/', Buffer.from(this.test.fullTitle()).toString('base64'), path)); } export function suiteRepeat(n: number, description: string, callback: (this: any) => void): void { diff --git a/src/vs/base/test/node/buffer.test.ts b/src/vs/base/test/node/buffer.test.ts new file mode 100644 index 00000000000..65f84a66ddf --- /dev/null +++ b/src/vs/base/test/node/buffer.test.ts @@ -0,0 +1,405 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { VSBuffer, bufferToReadable, readableToBuffer, bufferToStream, streamToBuffer, writeableBufferStream } from 'vs/base/common/buffer'; +import { timeout } from 'vs/base/common/async'; + +suite('Buffer', () => { + + test('issue #71993 - VSBuffer#toString returns numbers', () => { + const data = new Uint8Array([1, 2, 3, 'h'.charCodeAt(0), 'i'.charCodeAt(0), 4, 5]).buffer; + const buffer = VSBuffer.wrap(new Uint8Array(data, 3, 2)); + assert.deepEqual(buffer.toString(), 'hi'); + }); + + test('bufferToReadable / readableToBuffer', () => { + const content = 'Hello World'; + const readable = bufferToReadable(VSBuffer.fromString(content)); + + assert.equal(readableToBuffer(readable).toString(), content); + }); + + test('bufferToStream / streamToBuffer', async () => { + const content = 'Hello World'; + const stream = bufferToStream(VSBuffer.fromString(content)); + + assert.equal((await streamToBuffer(stream)).toString(), content); + }); + + test('bufferWriteableStream - basics (no error)', async () => { + const stream = writeableBufferStream(); + + let chunks: VSBuffer[] = []; + stream.on('data', data => { + chunks.push(data); + }); + + let ended = false; + stream.on('end', () => { + ended = true; + }); + + let errors: Error[] = []; + stream.on('error', error => { + errors.push(error); + }); + + await timeout(0); + stream.write(VSBuffer.fromString('Hello')); + await timeout(0); + stream.end(VSBuffer.fromString('World')); + + assert.equal(chunks.length, 2); + assert.equal(chunks[0].toString(), 'Hello'); + assert.equal(chunks[1].toString(), 'World'); + assert.equal(ended, true); + assert.equal(errors.length, 0); + }); + + test('bufferWriteableStream - basics (error)', async () => { + const stream = writeableBufferStream(); + + let chunks: VSBuffer[] = []; + stream.on('data', data => { + chunks.push(data); + }); + + let ended = false; + stream.on('end', () => { + ended = true; + }); + + let errors: Error[] = []; + stream.on('error', error => { + errors.push(error); + }); + + await timeout(0); + stream.write(VSBuffer.fromString('Hello')); + await timeout(0); + stream.end(new Error()); + + assert.equal(chunks.length, 1); + assert.equal(chunks[0].toString(), 'Hello'); + assert.equal(ended, true); + assert.equal(errors.length, 1); + }); + + test('bufferWriteableStream - buffers data when no listener', async () => { + const stream = writeableBufferStream(); + + await timeout(0); + stream.write(VSBuffer.fromString('Hello')); + await timeout(0); + stream.end(VSBuffer.fromString('World')); + + let chunks: VSBuffer[] = []; + stream.on('data', data => { + chunks.push(data); + }); + + let ended = false; + stream.on('end', () => { + ended = true; + }); + + let errors: Error[] = []; + stream.on('error', error => { + errors.push(error); + }); + + assert.equal(chunks.length, 1); + assert.equal(chunks[0].toString(), 'HelloWorld'); + assert.equal(ended, true); + assert.equal(errors.length, 0); + }); + + test('bufferWriteableStream - buffers errors when no listener', async () => { + const stream = writeableBufferStream(); + + await timeout(0); + stream.write(VSBuffer.fromString('Hello')); + await timeout(0); + stream.error(new Error()); + + let chunks: VSBuffer[] = []; + stream.on('data', data => { + chunks.push(data); + }); + + let errors: Error[] = []; + stream.on('error', error => { + errors.push(error); + }); + + let ended = false; + stream.on('end', () => { + ended = true; + }); + + stream.end(); + + assert.equal(chunks.length, 1); + assert.equal(chunks[0].toString(), 'Hello'); + assert.equal(ended, true); + assert.equal(errors.length, 1); + }); + + test('bufferWriteableStream - buffers end when no listener', async () => { + const stream = writeableBufferStream(); + + await timeout(0); + stream.write(VSBuffer.fromString('Hello')); + await timeout(0); + stream.end(VSBuffer.fromString('World')); + + let ended = false; + stream.on('end', () => { + ended = true; + }); + + let chunks: VSBuffer[] = []; + stream.on('data', data => { + chunks.push(data); + }); + + let errors: Error[] = []; + stream.on('error', error => { + errors.push(error); + }); + + assert.equal(chunks.length, 1); + assert.equal(chunks[0].toString(), 'HelloWorld'); + assert.equal(ended, true); + assert.equal(errors.length, 0); + }); + + test('bufferWriteableStream - nothing happens after end()', async () => { + const stream = writeableBufferStream(); + + let chunks: VSBuffer[] = []; + stream.on('data', data => { + chunks.push(data); + }); + + await timeout(0); + stream.write(VSBuffer.fromString('Hello')); + await timeout(0); + stream.end(VSBuffer.fromString('World')); + + let dataCalledAfterEnd = false; + stream.on('data', data => { + dataCalledAfterEnd = true; + }); + + let errorCalledAfterEnd = false; + stream.on('error', error => { + errorCalledAfterEnd = true; + }); + + let endCalledAfterEnd = false; + stream.on('end', () => { + endCalledAfterEnd = true; + }); + + await timeout(0); + stream.write(VSBuffer.fromString('Hello')); + await timeout(0); + stream.error(new Error()); + await timeout(0); + stream.end(VSBuffer.fromString('World')); + + assert.equal(dataCalledAfterEnd, false); + assert.equal(errorCalledAfterEnd, false); + assert.equal(endCalledAfterEnd, false); + + assert.equal(chunks.length, 2); + assert.equal(chunks[0].toString(), 'Hello'); + assert.equal(chunks[1].toString(), 'World'); + }); + + test('bufferWriteableStream - pause/resume (simple)', async () => { + const stream = writeableBufferStream(); + + let chunks: VSBuffer[] = []; + stream.on('data', data => { + chunks.push(data); + }); + + let ended = false; + stream.on('end', () => { + ended = true; + }); + + let errors: Error[] = []; + stream.on('error', error => { + errors.push(error); + }); + + stream.pause(); + + await timeout(0); + stream.write(VSBuffer.fromString('Hello')); + await timeout(0); + stream.end(VSBuffer.fromString('World')); + + assert.equal(chunks.length, 0); + assert.equal(errors.length, 0); + assert.equal(ended, false); + + stream.resume(); + + assert.equal(chunks.length, 1); + assert.equal(chunks[0].toString(), 'HelloWorld'); + assert.equal(ended, true); + assert.equal(errors.length, 0); + }); + + test('bufferWriteableStream - pause/resume (pause after first write)', async () => { + const stream = writeableBufferStream(); + + let chunks: VSBuffer[] = []; + stream.on('data', data => { + chunks.push(data); + }); + + let ended = false; + stream.on('end', () => { + ended = true; + }); + + let errors: Error[] = []; + stream.on('error', error => { + errors.push(error); + }); + + await timeout(0); + stream.write(VSBuffer.fromString('Hello')); + + stream.pause(); + + await timeout(0); + stream.end(VSBuffer.fromString('World')); + + assert.equal(chunks.length, 1); + assert.equal(chunks[0].toString(), 'Hello'); + assert.equal(errors.length, 0); + assert.equal(ended, false); + + stream.resume(); + + assert.equal(chunks.length, 2); + assert.equal(chunks[0].toString(), 'Hello'); + assert.equal(chunks[1].toString(), 'World'); + assert.equal(ended, true); + assert.equal(errors.length, 0); + }); + + test('bufferWriteableStream - pause/resume (error)', async () => { + const stream = writeableBufferStream(); + + let chunks: VSBuffer[] = []; + stream.on('data', data => { + chunks.push(data); + }); + + let ended = false; + stream.on('end', () => { + ended = true; + }); + + let errors: Error[] = []; + stream.on('error', error => { + errors.push(error); + }); + + stream.pause(); + + await timeout(0); + stream.write(VSBuffer.fromString('Hello')); + await timeout(0); + stream.end(new Error()); + + assert.equal(chunks.length, 0); + assert.equal(ended, false); + assert.equal(errors.length, 0); + + stream.resume(); + + assert.equal(chunks.length, 1); + assert.equal(chunks[0].toString(), 'Hello'); + assert.equal(ended, true); + assert.equal(errors.length, 1); + }); + + test('bufferWriteableStream - destroy', async () => { + const stream = writeableBufferStream(); + + let chunks: VSBuffer[] = []; + stream.on('data', data => { + chunks.push(data); + }); + + let ended = false; + stream.on('end', () => { + ended = true; + }); + + let errors: Error[] = []; + stream.on('error', error => { + errors.push(error); + }); + + stream.destroy(); + + await timeout(0); + stream.write(VSBuffer.fromString('Hello')); + await timeout(0); + stream.end(VSBuffer.fromString('World')); + + assert.equal(chunks.length, 0); + assert.equal(ended, false); + assert.equal(errors.length, 0); + }); + + test('Performance issue with VSBuffer#slice #76076', function () { + // Buffer#slice creates a view + { + const buff = Buffer.from([10, 20, 30, 40]); + const b2 = buff.slice(1, 3); + assert.equal(buff[1], 20); + assert.equal(b2[0], 20); + + buff[1] = 17; // modify buff AND b2 + assert.equal(buff[1], 17); + assert.equal(b2[0], 17); + } + + // TypedArray#slice creates a copy + { + const unit = new Uint8Array([10, 20, 30, 40]); + const u2 = unit.slice(1, 3); + assert.equal(unit[1], 20); + assert.equal(u2[0], 20); + + unit[1] = 17; // modify unit, NOT b2 + assert.equal(unit[1], 17); + assert.equal(u2[0], 20); + } + + // TypedArray#subarray creates a view + { + const unit = new Uint8Array([10, 20, 30, 40]); + const u2 = unit.subarray(1, 3); + assert.equal(unit[1], 20); + assert.equal(u2[0], 20); + + unit[1] = 17; // modify unit AND b2 + assert.equal(unit[1], 17); + assert.equal(u2[0], 17); + } + }); +}); diff --git a/src/vs/base/test/node/config.test.ts b/src/vs/base/test/node/config.test.ts index 59df2e0d36f..3fa8f78de68 100644 --- a/src/vs/base/test/node/config.test.ts +++ b/src/vs/base/test/node/config.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import * as os from 'os'; -import * as path from 'path'; +import * as path from 'vs/base/common/path'; import * as fs from 'fs'; import * as uuid from 'vs/base/common/uuid'; import { ConfigWatcher } from 'vs/base/node/config'; @@ -20,7 +20,7 @@ suite('Config', () => { const newDir = path.join(parentDir, 'config', id); const testFile = path.join(newDir, 'config.json'); - let watcher = new ConfigWatcher(testFile); + let watcher = new ConfigWatcher<{}>(testFile); let config = watcher.getConfig(); assert.ok(config); diff --git a/src/vs/base/test/node/console.test.ts b/src/vs/base/test/node/console.test.ts index af88880bac9..e7a243a2d42 100644 --- a/src/vs/base/test/node/console.test.ts +++ b/src/vs/base/test/node/console.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { getFirstFrame } from 'vs/base/node/console'; -import { normalize } from 'path'; +import { getFirstFrame } from 'vs/base/common/console'; +import { normalize } from 'vs/base/common/path'; suite('Console', () => { diff --git a/src/vs/base/test/node/encoding/encoding.test.ts b/src/vs/base/test/node/encoding/encoding.test.ts index db9cc560e5a..77ad22264cf 100644 --- a/src/vs/base/test/node/encoding/encoding.test.ts +++ b/src/vs/base/test/node/encoding/encoding.test.ts @@ -6,43 +6,114 @@ import * as assert from 'assert'; import * as fs from 'fs'; import * as encoding from 'vs/base/node/encoding'; -import { readExactlyByFile } from 'vs/base/node/stream'; import { Readable } from 'stream'; import { getPathFromAmdModule } from 'vs/base/common/amd'; +export async function detectEncodingByBOM(file: string): Promise { + try { + const { buffer, bytesRead } = await readExactlyByFile(file, 3); + + return encoding.detectEncodingByBOMFromBuffer(buffer, bytesRead); + } catch (error) { + return null; // ignore errors (like file not found) + } +} + +interface ReadResult { + buffer: Buffer | null; + bytesRead: number; +} + +function readExactlyByFile(file: string, totalBytes: number): Promise { + return new Promise((resolve, reject) => { + fs.open(file, 'r', null, (err, fd) => { + if (err) { + return reject(err); + } + + function end(err: Error | null, resultBuffer: Buffer | null, bytesRead: number): void { + fs.close(fd, closeError => { + if (closeError) { + return reject(closeError); + } + + if (err && (err).code === 'EISDIR') { + return reject(err); // we want to bubble this error up (file is actually a folder) + } + + return resolve({ buffer: resultBuffer, bytesRead }); + }); + } + + const buffer = Buffer.allocUnsafe(totalBytes); + let offset = 0; + + function readChunk(): void { + fs.read(fd, buffer, offset, totalBytes - offset, null, (err, bytesRead) => { + if (err) { + return end(err, null, 0); + } + + if (bytesRead === 0) { + return end(null, buffer, offset); + } + + offset += bytesRead; + + if (offset === totalBytes) { + return end(null, buffer, offset); + } + + return readChunk(); + }); + } + + readChunk(); + }); + }); +} + suite('Encoding', () => { + + test('detectBOM does not return error for non existing file', async () => { + const file = getPathFromAmdModule(require, './fixtures/not-exist.css'); + + const detectedEncoding = await detectEncodingByBOM(file); + assert.equal(detectedEncoding, null); + }); + test('detectBOM UTF-8', async () => { const file = getPathFromAmdModule(require, './fixtures/some_utf8.css'); - const detectedEncoding = await encoding.detectEncodingByBOM(file); + const detectedEncoding = await detectEncodingByBOM(file); assert.equal(detectedEncoding, 'utf8'); }); test('detectBOM UTF-16 LE', async () => { const file = getPathFromAmdModule(require, './fixtures/some_utf16le.css'); - const detectedEncoding = await encoding.detectEncodingByBOM(file); + const detectedEncoding = await detectEncodingByBOM(file); assert.equal(detectedEncoding, 'utf16le'); }); test('detectBOM UTF-16 BE', async () => { const file = getPathFromAmdModule(require, './fixtures/some_utf16be.css'); - const detectedEncoding = await encoding.detectEncodingByBOM(file); + const detectedEncoding = await detectEncodingByBOM(file); assert.equal(detectedEncoding, 'utf16be'); }); test('detectBOM ANSI', async function () { const file = getPathFromAmdModule(require, './fixtures/some_ansi.css'); - const detectedEncoding = await encoding.detectEncodingByBOM(file); + const detectedEncoding = await detectEncodingByBOM(file); assert.equal(detectedEncoding, null); }); test('detectBOM ANSI', async function () { const file = getPathFromAmdModule(require, './fixtures/empty.txt'); - const detectedEncoding = await encoding.detectEncodingByBOM(file); + const detectedEncoding = await detectEncodingByBOM(file); assert.equal(detectedEncoding, null); }); @@ -132,13 +203,13 @@ suite('Encoding', () => { assert.equal(mimes.encoding, 'windows1252'); }); - async function readAndDecodeFromDisk(path, _encoding) { + async function readAndDecodeFromDisk(path: string, fileEncoding: string | null) { return new Promise((resolve, reject) => { fs.readFile(path, (err, data) => { if (err) { reject(err); } else { - resolve(encoding.decode(data, _encoding)); + resolve(encoding.decode(data, fileEncoding!)); } }); }); @@ -169,7 +240,7 @@ suite('Encoding', () => { } }); - let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 4 }); + let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 4, guessEncoding: false, overwriteEncoding: detected => detected || encoding.UTF8 }); assert.ok(detected); assert.ok(stream); @@ -189,7 +260,7 @@ suite('Encoding', () => { } }); - let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 64 }); + let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 64, guessEncoding: false, overwriteEncoding: detected => detected || encoding.UTF8 }); assert.ok(detected); assert.ok(stream); @@ -206,7 +277,7 @@ suite('Encoding', () => { } }); - let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 512 }); + let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 512, guessEncoding: false, overwriteEncoding: detected => detected || encoding.UTF8 }); assert.ok(detected); assert.ok(stream); @@ -221,7 +292,7 @@ suite('Encoding', () => { let path = getPathFromAmdModule(require, './fixtures/some_utf16be.css'); let source = fs.createReadStream(path); - let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 64 }); + let { detected, stream } = await encoding.toDecodeStream(source, { minBytesRequiredForDetection: 64, guessEncoding: false, overwriteEncoding: detected => detected || encoding.UTF8 }); assert.equal(detected.encoding, 'utf16be'); assert.equal(detected.seemsBinary, false); @@ -236,7 +307,7 @@ suite('Encoding', () => { let path = getPathFromAmdModule(require, './fixtures/empty.txt'); let source = fs.createReadStream(path); - let { detected, stream } = await encoding.toDecodeStream(source, {}); + let { detected, stream } = await encoding.toDecodeStream(source, { guessEncoding: false, overwriteEncoding: detected => detected || encoding.UTF8 }); let expected = await readAndDecodeFromDisk(path, detected.encoding); let actual = await readAllAsString(stream); diff --git a/src/vs/base/test/node/extfs/extfs.test.ts b/src/vs/base/test/node/extfs/extfs.test.ts deleted file mode 100644 index 100de754c29..00000000000 --- a/src/vs/base/test/node/extfs/extfs.test.ts +++ /dev/null @@ -1,617 +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 * as assert from 'assert'; -import * as fs from 'fs'; -import * as os from 'os'; -import * as path from 'path'; -import { Readable } from 'stream'; -import { canNormalize } from 'vs/base/common/normalization'; -import { isLinux, isWindows } from 'vs/base/common/platform'; -import * as uuid from 'vs/base/common/uuid'; -import * as extfs from 'vs/base/node/extfs'; -import { getPathFromAmdModule } from 'vs/base/common/amd'; -import { CancellationTokenSource } from 'vs/base/common/cancellation'; - -const ignore = () => { }; - -const mkdirp = (path: string, mode: number, callback: (error) => void) => { - extfs.mkdirp(path, mode).then(() => callback(null), error => callback(error)); -}; - -const chunkSize = 64 * 1024; -const readError = 'Error while reading'; -function toReadable(value: string, throwError?: boolean): Readable { - const totalChunks = Math.ceil(value.length / chunkSize); - const stringChunks: string[] = []; - - for (let i = 0, j = 0; i < totalChunks; ++i, j += chunkSize) { - stringChunks[i] = value.substr(j, chunkSize); - } - - let counter = 0; - return new Readable({ - read: function () { - if (throwError) { - this.emit('error', new Error(readError)); - } - - let res!: string; - let canPush = true; - while (canPush && (res = stringChunks[counter++])) { - canPush = this.push(res); - } - - // EOS - if (!res) { - this.push(null); - } - }, - encoding: 'utf8' - }); -} - -suite('Extfs', () => { - - test('mkdirp', function (done) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(newDir)); - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); // 493 = 0755 - }); - - test('stat link', function (done) { - if (isWindows) { - // Symlinks are not the same on win, and we can not create them programitically without admin privileges - return done(); - } - - const id1 = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id1); - const directory = path.join(parentDir, 'extfs', id1); - - const id2 = uuid.generateUuid(); - const symbolicLink = path.join(parentDir, 'extfs', id2); - - mkdirp(directory, 493, error => { - if (error) { - return done(error); - } - - fs.symlinkSync(directory, symbolicLink); - - extfs.statLink(directory, (error, statAndIsLink) => { - if (error) { - return done(error); - } - - assert.ok(!statAndIsLink!.isSymbolicLink); - - extfs.statLink(symbolicLink, (error, statAndIsLink) => { - if (error) { - return done(error); - } - - assert.ok(statAndIsLink!.isSymbolicLink); - extfs.delSync(directory); - done(); - }); - }); - }); - }); - - test('delSync - swallows file not found error', function () { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - extfs.delSync(newDir); - - assert.ok(!fs.existsSync(newDir)); - }); - - test('delSync - simple', function (done) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); - - extfs.delSync(newDir); - - assert.ok(!fs.existsSync(newDir)); - done(); - }); // 493 = 0755 - }); - - test('delSync - recursive folder structure', function (done) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); - - fs.mkdirSync(path.join(newDir, 'somefolder')); - fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); - - extfs.delSync(newDir); - - assert.ok(!fs.existsSync(newDir)); - done(); - }); // 493 = 0755 - }); - - test('copy, move and delete', function (done) { - const id = uuid.generateUuid(); - const id2 = uuid.generateUuid(); - const sourceDir = getPathFromAmdModule(require, './fixtures'); - const parentDir = path.join(os.tmpdir(), 'vsctests', 'extfs'); - const targetDir = path.join(parentDir, id); - const targetDir2 = path.join(parentDir, id2); - - extfs.copy(sourceDir, targetDir, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(targetDir)); - assert.ok(fs.existsSync(path.join(targetDir, 'index.html'))); - assert.ok(fs.existsSync(path.join(targetDir, 'site.css'))); - assert.ok(fs.existsSync(path.join(targetDir, 'examples'))); - assert.ok(fs.statSync(path.join(targetDir, 'examples')).isDirectory()); - assert.ok(fs.existsSync(path.join(targetDir, 'examples', 'small.jxs'))); - - extfs.mv(targetDir, targetDir2, error => { - if (error) { - return done(error); - } - - assert.ok(!fs.existsSync(targetDir)); - assert.ok(fs.existsSync(targetDir2)); - assert.ok(fs.existsSync(path.join(targetDir2, 'index.html'))); - assert.ok(fs.existsSync(path.join(targetDir2, 'site.css'))); - assert.ok(fs.existsSync(path.join(targetDir2, 'examples'))); - assert.ok(fs.statSync(path.join(targetDir2, 'examples')).isDirectory()); - assert.ok(fs.existsSync(path.join(targetDir2, 'examples', 'small.jxs'))); - - extfs.mv(path.join(targetDir2, 'index.html'), path.join(targetDir2, 'index_moved.html'), error => { - if (error) { - return done(error); - } - - assert.ok(!fs.existsSync(path.join(targetDir2, 'index.html'))); - assert.ok(fs.existsSync(path.join(targetDir2, 'index_moved.html'))); - - extfs.del(parentDir, os.tmpdir(), error => { - if (error) { - return done(error); - } - }, error => { - if (error) { - return done(error); - } - assert.ok(!fs.existsSync(parentDir)); - done(); - }); - }); - }); - }); - }); - - test('readdir', function (done) { - if (canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id, 'öäü'); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(newDir)); - - extfs.readdir(path.join(parentDir, 'extfs', id), (error, children) => { - assert.equal(children.some(n => n === 'öäü'), true); // Mac always converts to NFD, so - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); // 493 = 0755 - } else { - done(); - } - }); - - test('writeFileAndFlush (string)', function (done) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - const testFile = path.join(newDir, 'flushed.txt'); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(newDir)); - - extfs.writeFileAndFlush(testFile, 'Hello World', null!, error => { - if (error) { - return done(error); - } - - assert.equal(fs.readFileSync(testFile), 'Hello World'); - - const largeString = (new Array(100 * 1024)).join('Large String\n'); - - extfs.writeFileAndFlush(testFile, largeString, null!, error => { - if (error) { - return done(error); - } - - assert.equal(fs.readFileSync(testFile), largeString); - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - }); - }); - - test('writeFileAndFlush (stream)', function (done) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - const testFile = path.join(newDir, 'flushed.txt'); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(newDir)); - - extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null!, error => { - if (error) { - return done(error); - } - - assert.equal(fs.readFileSync(testFile), 'Hello World'); - - const largeString = (new Array(100 * 1024)).join('Large String\n'); - - extfs.writeFileAndFlush(testFile, toReadable(largeString), null!, error => { - if (error) { - return done(error); - } - - assert.equal(fs.readFileSync(testFile), largeString); - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - }); - }); - - test('writeFileAndFlush (file stream)', function (done) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const sourceFile = getPathFromAmdModule(require, './fixtures/index.html'); - const newDir = path.join(parentDir, 'extfs', id); - const testFile = path.join(newDir, 'flushed.txt'); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(newDir)); - - extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null!, error => { - if (error) { - return done(error); - } - - assert.equal(fs.readFileSync(testFile).toString(), fs.readFileSync(sourceFile).toString()); - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - }); - - test('writeFileAndFlush (string, error handling)', function (done) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - const testFile = path.join(newDir, 'flushed.txt'); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(newDir)); - - fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory! - - extfs.writeFileAndFlush(testFile, 'Hello World', null!, error => { - if (!error) { - return done(new Error('Expected error for writing to readonly file')); - } - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - }); - - test('writeFileAndFlush (stream, error handling EISDIR)', function (done) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - const testFile = path.join(newDir, 'flushed.txt'); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(newDir)); - - fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory! - - const readable = toReadable('Hello World'); - extfs.writeFileAndFlush(testFile, readable, null!, error => { - if (!error || (error).code !== 'EISDIR') { - return done(new Error('Expected EISDIR error for writing to folder but got: ' + (error ? (error).code : 'no error'))); - } - - // verify that the stream is still consumable (for https://github.com/Microsoft/vscode/issues/42542) - assert.equal(readable.read(), 'Hello World'); - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - }); - - test('writeFileAndFlush (stream, error handling READERROR)', function (done) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - const testFile = path.join(newDir, 'flushed.txt'); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(newDir)); - - extfs.writeFileAndFlush(testFile, toReadable('Hello World', true /* throw error */), null!, error => { - if (!error || error.message !== readError) { - return done(new Error('Expected error for writing to folder')); - } - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - }); - - test('writeFileAndFlush (stream, error handling EACCES)', function (done) { - if (isLinux) { - return done(); // somehow this test fails on Linux in our TFS builds - } - - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - const testFile = path.join(newDir, 'flushed.txt'); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(newDir)); - - fs.writeFileSync(testFile, ''); - fs.chmodSync(testFile, 33060); // make readonly - - extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null!, error => { - if (!error || !((error).code !== 'EACCES' || (error).code !== 'EPERM')) { - return done(new Error('Expected EACCES/EPERM error for writing to folder but got: ' + (error ? (error).code : 'no error'))); - } - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - }); - - test('writeFileAndFlush (file stream, error handling)', function (done) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const sourceFile = getPathFromAmdModule(require, './fixtures/index.html'); - const newDir = path.join(parentDir, 'extfs', id); - const testFile = path.join(newDir, 'flushed.txt'); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(newDir)); - - fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory! - - extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null!, error => { - if (!error) { - return done(new Error('Expected error for writing to folder')); - } - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - }); - - test('writeFileAndFlushSync', function (done) { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - const testFile = path.join(newDir, 'flushed.txt'); - - mkdirp(newDir, 493, error => { - if (error) { - return done(error); - } - - assert.ok(fs.existsSync(newDir)); - - extfs.writeFileAndFlushSync(testFile, 'Hello World', null!); - assert.equal(fs.readFileSync(testFile), 'Hello World'); - - const largeString = (new Array(100 * 1024)).join('Large String\n'); - - extfs.writeFileAndFlushSync(testFile, largeString, null!); - assert.equal(fs.readFileSync(testFile), largeString); - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - - test('realcase', (done) => { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - mkdirp(newDir, 493, error => { - - // assume case insensitive file system - if (process.platform === 'win32' || process.platform === 'darwin') { - const upper = newDir.toUpperCase(); - const real = extfs.realcaseSync(upper); - - if (real) { // can be null in case of permission errors - assert.notEqual(real, upper); - assert.equal(real.toUpperCase(), upper); - assert.equal(real, newDir); - } - } - - // linux, unix, etc. -> assume case sensitive file system - else { - const real = extfs.realcaseSync(newDir); - assert.equal(real, newDir); - } - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - - test('realpath', (done) => { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - mkdirp(newDir, 493, error => { - - extfs.realpath(newDir, (error, realpath) => { - assert.ok(realpath); - assert.ok(!error); - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - }); - - test('realpathSync', (done) => { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - mkdirp(newDir, 493, error => { - let realpath!: string; - try { - realpath = extfs.realpathSync(newDir); - } catch (error) { - assert.ok(!error); - } - assert.ok(realpath!); - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - - test('mkdirp cancellation', (done) => { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - const source = new CancellationTokenSource(); - - const mkdirpPromise = extfs.mkdirp(newDir, 493, source.token); - source.cancel(); - - return mkdirpPromise.then(res => { - assert.equal(res, false); - - extfs.del(parentDir, os.tmpdir(), done, ignore); - }); - }); - - test('sanitizeFilePath', () => { - if (isWindows) { - assert.equal(extfs.sanitizeFilePath('.', 'C:\\the\\cwd'), 'C:\\the\\cwd'); - assert.equal(extfs.sanitizeFilePath('', 'C:\\the\\cwd'), 'C:\\the\\cwd'); - - assert.equal(extfs.sanitizeFilePath('C:', 'C:\\the\\cwd'), 'C:\\'); - assert.equal(extfs.sanitizeFilePath('C:\\', 'C:\\the\\cwd'), 'C:\\'); - assert.equal(extfs.sanitizeFilePath('C:\\\\', 'C:\\the\\cwd'), 'C:\\'); - - assert.equal(extfs.sanitizeFilePath('C:\\folder\\my.txt', 'C:\\the\\cwd'), 'C:\\folder\\my.txt'); - assert.equal(extfs.sanitizeFilePath('C:\\folder\\my', 'C:\\the\\cwd'), 'C:\\folder\\my'); - assert.equal(extfs.sanitizeFilePath('C:\\folder\\..\\my', 'C:\\the\\cwd'), 'C:\\my'); - assert.equal(extfs.sanitizeFilePath('C:\\folder\\my\\', 'C:\\the\\cwd'), 'C:\\folder\\my'); - assert.equal(extfs.sanitizeFilePath('C:\\folder\\my\\\\\\', 'C:\\the\\cwd'), 'C:\\folder\\my'); - - assert.equal(extfs.sanitizeFilePath('my.txt', 'C:\\the\\cwd'), 'C:\\the\\cwd\\my.txt'); - assert.equal(extfs.sanitizeFilePath('my.txt\\', 'C:\\the\\cwd'), 'C:\\the\\cwd\\my.txt'); - - assert.equal(extfs.sanitizeFilePath('\\\\localhost\\folder\\my', 'C:\\the\\cwd'), '\\\\localhost\\folder\\my'); - assert.equal(extfs.sanitizeFilePath('\\\\localhost\\folder\\my\\', 'C:\\the\\cwd'), '\\\\localhost\\folder\\my'); - } else { - assert.equal(extfs.sanitizeFilePath('.', '/the/cwd'), '/the/cwd'); - assert.equal(extfs.sanitizeFilePath('', '/the/cwd'), '/the/cwd'); - assert.equal(extfs.sanitizeFilePath('/', '/the/cwd'), '/'); - - assert.equal(extfs.sanitizeFilePath('/folder/my.txt', '/the/cwd'), '/folder/my.txt'); - assert.equal(extfs.sanitizeFilePath('/folder/my', '/the/cwd'), '/folder/my'); - assert.equal(extfs.sanitizeFilePath('/folder/../my', '/the/cwd'), '/my'); - assert.equal(extfs.sanitizeFilePath('/folder/my/', '/the/cwd'), '/folder/my'); - assert.equal(extfs.sanitizeFilePath('/folder/my///', '/the/cwd'), '/folder/my'); - - assert.equal(extfs.sanitizeFilePath('my.txt', '/the/cwd'), '/the/cwd/my.txt'); - assert.equal(extfs.sanitizeFilePath('my.txt/', '/the/cwd'), '/the/cwd/my.txt'); - } - }); -}); diff --git a/src/vs/base/test/node/extpath.test.ts b/src/vs/base/test/node/extpath.test.ts new file mode 100644 index 00000000000..e435d624801 --- /dev/null +++ b/src/vs/base/test/node/extpath.test.ts @@ -0,0 +1,73 @@ +/*--------------------------------------------------------------------------------------------- + * 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 os from 'os'; +import * as path from 'vs/base/common/path'; +import * as uuid from 'vs/base/common/uuid'; +import * as pfs from 'vs/base/node/pfs'; +import { realcaseSync, realpath, realpathSync } from 'vs/base/node/extpath'; + +suite('Extpath', () => { + + test('realcase', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'extpath', id); + + await pfs.mkdirp(newDir, 493); + + // assume case insensitive file system + if (process.platform === 'win32' || process.platform === 'darwin') { + const upper = newDir.toUpperCase(); + const real = realcaseSync(upper); + + if (real) { // can be null in case of permission errors + assert.notEqual(real, upper); + assert.equal(real.toUpperCase(), upper); + assert.equal(real, newDir); + } + } + + // linux, unix, etc. -> assume case sensitive file system + else { + const real = realcaseSync(newDir); + assert.equal(real, newDir); + } + + await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + }); + + test('realpath', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'extpath', id); + + await pfs.mkdirp(newDir, 493); + + const realpathVal = await realpath(newDir); + assert.ok(realpathVal); + + await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + }); + + test('realpathSync', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'extpath', id); + + await pfs.mkdirp(newDir, 493); + + let realpath!: string; + try { + realpath = realpathSync(newDir); + } catch (error) { + assert.ok(!error); + } + assert.ok(realpath!); + + await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + }); +}); diff --git a/src/vs/base/test/node/flow.test.ts b/src/vs/base/test/node/flow.test.ts deleted file mode 100644 index 12b5aea89e0..00000000000 --- a/src/vs/base/test/node/flow.test.ts +++ /dev/null @@ -1,488 +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 * as assert from 'assert'; -import * as flow from 'vs/base/node/flow'; - -const loop = flow.loop; -const sequence = flow.sequence; -const parallel = flow.parallel; - -suite('Flow', () => { - function assertCounterEquals(counter: number, expected: number): void { - assert.ok(counter === expected, 'Expected ' + expected + ' assertions, but got ' + counter); - } - - function syncThrowsError(callback: any): void { - callback(new Error('foo'), null); - } - - function syncSequenceGetThrowsError(value: any, callback: any) { - sequence( - function onError(error) { - callback(error, null); - }, - - function getFirst(this: any) { - syncThrowsError(this); - }, - - function handleFirst(first: number) { - //Foo - } - ); - } - - function syncGet(value: any, callback: any): void { - callback(null, value); - } - - function syncGetError(value: any, callback: any): void { - callback(new Error(''), null); - } - - function asyncGet(value: any, callback: any): void { - process.nextTick(function () { - callback(null, value); - }); - } - - function asyncGetError(value: any, callback: any): void { - process.nextTick(function () { - callback(new Error(''), null); - }); - } - - test('loopSync', function (done: () => void) { - const elements = ['1', '2', '3']; - loop(elements, function (element, callback, index, total) { - assert.ok(index === 0 || index === 1 || index === 2); - assert.deepEqual(3, total); - callback(null, element); - }, function (error, result) { - assert.equal(error, null); - assert.deepEqual(result, elements); - - done(); - }); - }); - - test('loopByFunctionSync', function (done: () => void) { - const elements = function (callback: Function) { - callback(null, ['1', '2', '3']); - }; - - loop(elements, function (element, callback) { - callback(null, element); - }, function (error, result) { - assert.equal(error, null); - assert.deepEqual(result, ['1', '2', '3']); - - done(); - }); - }); - - test('loopByFunctionAsync', function (done: () => void) { - const elements = function (callback: Function) { - process.nextTick(function () { - callback(null, ['1', '2', '3']); - }); - }; - - loop(elements, function (element, callback) { - callback(null, element); - }, function (error, result) { - assert.equal(error, null); - assert.deepEqual(result, ['1', '2', '3']); - - done(); - }); - }); - - test('loopSyncErrorByThrow', function (done: () => void) { - const elements = ['1', '2', '3']; - loop(elements, function (element, callback) { - if (element === '2') { - throw new Error('foo'); - } else { - callback(null, element); - } - }, function (error, result) { - assert.ok(error); - assert.ok(!result); - - done(); - }); - }); - - test('loopSyncErrorByCallback', function (done: () => void) { - const elements = ['1', '2', '3']; - loop(elements, function (element, callback) { - if (element === '2') { - callback(new Error('foo'), null); - } else { - callback(null, element); - } - }, function (error, result) { - assert.ok(error); - assert.ok(!result); - - done(); - }); - }); - - test('loopAsync', function (done: () => void) { - const elements = ['1', '2', '3']; - loop(elements, function (element, callback) { - process.nextTick(function () { - callback(null, element); - }); - }, function (error, result) { - assert.equal(error, null); - assert.deepEqual(result, elements); - - done(); - }); - }); - - test('loopAsyncErrorByCallback', function (done: () => void) { - const elements = ['1', '2', '3']; - loop(elements, function (element, callback) { - process.nextTick(function () { - if (element === '2') { - callback(new Error('foo'), null); - } else { - callback(null, element); - } - }); - }, function (error, result) { - assert.ok(error); - assert.ok(!result); - - done(); - }); - }); - - test('sequenceSync', function (done: () => void) { - let assertionCount = 0; - let errorCount = 0; - - sequence( - function onError(error) { - errorCount++; - }, - - function getFirst(this: any) { - syncGet('1', this); - }, - - function handleFirst(this: any, first: number) { - assert.deepEqual('1', first); - assertionCount++; - syncGet('2', this); - }, - - function handleSecond(this: any, second: any) { - assert.deepEqual('2', second); - assertionCount++; - syncGet(null, this); - }, - - function handleThird(third: any) { - assert.ok(!third); - assertionCount++; - - assertCounterEquals(assertionCount, 3); - assertCounterEquals(errorCount, 0); - done(); - } - ); - }); - - test('sequenceAsync', function (done: () => void) { - let assertionCount = 0; - let errorCount = 0; - - sequence( - function onError(error) { - errorCount++; - }, - - function getFirst(this: any) { - asyncGet('1', this); - }, - - function handleFirst(this: any, first: number) { - assert.deepEqual('1', first); - assertionCount++; - asyncGet('2', this); - }, - - function handleSecond(this: any, second: number) { - assert.deepEqual('2', second); - assertionCount++; - asyncGet(null, this); - }, - - function handleThird(third: number) { - assert.ok(!third); - assertionCount++; - - assertCounterEquals(assertionCount, 3); - assertCounterEquals(errorCount, 0); - done(); - } - ); - }); - - test('sequenceSyncErrorByThrow', function (done: () => void) { - let assertionCount = 0; - let errorCount = 0; - - sequence( - function onError(error) { - errorCount++; - - assertCounterEquals(assertionCount, 1); - assertCounterEquals(errorCount, 1); - done(); - }, - - function getFirst(this: any) { - syncGet('1', this); - }, - - function handleFirst(this: any, first: number) { - assert.deepEqual('1', first); - assertionCount++; - syncGet('2', this); - }, - - function handleSecond(second: number) { - if (true) { - throw new Error(''); - } - // assertionCount++; - // syncGet(null, this); - }, - - function handleThird(third: number) { - throw new Error('We should not be here'); - } - ); - }); - - test('sequenceSyncErrorByCallback', function (done: () => void) { - let assertionCount = 0; - let errorCount = 0; - - sequence( - function onError(error) { - errorCount++; - - assertCounterEquals(assertionCount, 1); - assertCounterEquals(errorCount, 1); - done(); - }, - - function getFirst(this: any) { - syncGet('1', this); - }, - - function handleFirst(this: any, first: number) { - assert.deepEqual('1', first); - assertionCount++; - syncGetError('2', this); - }, - - function handleSecond(second: number) { - throw new Error('We should not be here'); - } - ); - }); - - test('sequenceAsyncErrorByThrow', function (done: () => void) { - let assertionCount = 0; - let errorCount = 0; - - sequence( - function onError(error) { - errorCount++; - - assertCounterEquals(assertionCount, 1); - assertCounterEquals(errorCount, 1); - done(); - }, - - function getFirst(this: any) { - asyncGet('1', this); - }, - - function handleFirst(this: any, first: number) { - assert.deepEqual('1', first); - assertionCount++; - asyncGet('2', this); - }, - - function handleSecond(second: number) { - if (true) { - throw new Error(''); - } - // assertionCount++; - // asyncGet(null, this); - }, - - function handleThird(third: number) { - throw new Error('We should not be here'); - } - ); - }); - - test('sequenceAsyncErrorByCallback', function (done: () => void) { - let assertionCount = 0; - let errorCount = 0; - - sequence( - function onError(error) { - errorCount++; - - assertCounterEquals(assertionCount, 1); - assertCounterEquals(errorCount, 1); - done(); - }, - - function getFirst(this: any) { - asyncGet('1', this); - }, - - function handleFirst(this: any, first: number) { - assert.deepEqual('1', first); - assertionCount++; - asyncGetError('2', this); - }, - - function handleSecond(second: number) { - throw new Error('We should not be here'); - } - ); - }); - - test('syncChainedSequenceError', function (done: () => void) { - sequence( - function onError(error) { - done(); - }, - - function getFirst(this: any) { - syncSequenceGetThrowsError('1', this); - } - ); - }); - - test('tolerateBooleanResults', function (done: () => void) { - let assertionCount = 0; - let errorCount = 0; - - sequence( - function onError(error) { - errorCount++; - }, - - function getFirst(this: any) { - this(true); - }, - - function getSecond(this: any, result: boolean) { - assert.equal(result, true); - this(false); - }, - - function last(result: boolean) { - assert.equal(result, false); - assertionCount++; - - assertCounterEquals(assertionCount, 1); - assertCounterEquals(errorCount, 0); - done(); - } - ); - }); - - test('loopTolerateBooleanResults', function (done: () => void) { - let elements = ['1', '2', '3']; - loop(elements, function (element, callback) { - process.nextTick(function () { - (callback)(true); - }); - }, function (error, result) { - assert.equal(error, null); - assert.deepEqual(result, [true, true, true]); - - done(); - }); - }); - - test('parallel', function (done: () => void) { - let elements = [1, 2, 3, 4, 5]; - let sum = 0; - - parallel(elements, function (element, callback) { - sum += element; - callback(null!, element * element); - }, function (errors, result) { - assert.ok(!errors); - - assert.deepEqual(sum, 15); - assert.deepEqual(result, [1, 4, 9, 16, 25]); - - done(); - }); - }); - - test('parallel - setTimeout', function (done: () => void) { - let elements = [1, 2, 3, 4, 5]; - let timeouts = [10, 30, 5, 0, 4]; - let sum = 0; - - parallel(elements, function (element, callback) { - setTimeout(function () { - sum += element; - callback(null!, element * element); - }, timeouts.pop()); - }, function (errors, result) { - assert.ok(!errors); - - assert.deepEqual(sum, 15); - assert.deepEqual(result, [1, 4, 9, 16, 25]); - - done(); - }); - }); - - test('parallel - with error', function (done: () => void) { - const elements = [1, 2, 3, 4, 5]; - const timeouts = [10, 30, 5, 0, 4]; - let sum = 0; - - parallel(elements, function (element, callback) { - setTimeout(function () { - if (element === 4) { - callback(new Error('error!'), null!); - } else { - sum += element; - callback(null!, element * element); - } - }, timeouts.pop()); - }, function (errors, result) { - assert.ok(errors); - assert.deepEqual(errors, [null, null, null, new Error('error!'), null]); - - assert.deepEqual(sum, 11); - assert.deepEqual(result, [1, 4, 9, null, 25]); - - done(); - }); - }); -}); \ No newline at end of file diff --git a/src/vs/base/test/node/glob.test.ts b/src/vs/base/test/node/glob.test.ts index 7b003cc002b..53170961b90 100644 --- a/src/vs/base/test/node/glob.test.ts +++ b/src/vs/base/test/node/glob.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import * as path from 'path'; +import * as path from 'vs/base/common/path'; import * as glob from 'vs/base/common/glob'; import { isWindows } from 'vs/base/common/platform'; @@ -102,6 +102,9 @@ suite('Glob', () => { p = 'C:/DNXConsoleApp/**/*.cs'; assertGlobMatch(p, 'C:\\DNXConsoleApp\\Program.cs'); assertGlobMatch(p, 'C:\\DNXConsoleApp\\foo\\Program.cs'); + + p = '*'; + assertGlobMatch(p, ''); }); test('dot hidden', function () { @@ -428,7 +431,7 @@ suite('Glob', () => { test('expression support (single)', function () { let siblings = ['test.html', 'test.txt', 'test.ts', 'test.js']; - let hasSibling = name => siblings.indexOf(name) !== -1; + let hasSibling = (name: string) => siblings.indexOf(name) !== -1; // { "**/*.js": { "when": "$(basename).ts" } } let expression: glob.IExpression = { @@ -452,7 +455,7 @@ suite('Glob', () => { expression = { '**/*.js': { - } + } as any }; assert.strictEqual('**/*.js', glob.match(expression, 'test.js', hasSibling)); @@ -464,14 +467,14 @@ suite('Glob', () => { test('expression support (multiple)', function () { let siblings = ['test.html', 'test.txt', 'test.ts', 'test.js']; - let hasSibling = name => siblings.indexOf(name) !== -1; + let hasSibling = (name: string) => siblings.indexOf(name) !== -1; // { "**/*.js": { "when": "$(basename).ts" } } let expression: glob.IExpression = { '**/*.js': { when: '$(basename).ts' }, '**/*.as': true, '**/*.foo': false, - '**/*.bananas': { bananas: true } + '**/*.bananas': { bananas: true } as any }; assert.strictEqual('**/*.js', glob.match(expression, 'test.js', hasSibling)); @@ -688,7 +691,7 @@ suite('Glob', () => { }); test('expression with other falsy value', function () { - let expr = { '**/*.js': 0 }; + let expr = { '**/*.js': 0 } as any; assert.strictEqual(glob.match(expr, 'foo.js'), '**/*.js'); }); @@ -714,12 +717,15 @@ suite('Glob', () => { }; let siblings = ['foo.ts', 'foo.js', 'foo', 'bar']; - let hasSibling = name => siblings.indexOf(name) !== -1; + let hasSibling = (name: string) => siblings.indexOf(name) !== -1; assert.strictEqual(glob.match(expr, 'bar', hasSibling), '**/bar'); assert.strictEqual(glob.match(expr, 'foo', hasSibling), null); assert.strictEqual(glob.match(expr, 'foo/bar', hasSibling), '**/bar'); - assert.strictEqual(glob.match(expr, 'foo\\bar', hasSibling), '**/bar'); + if (isWindows) { + // backslash is a valid file name character on posix + assert.strictEqual(glob.match(expr, 'foo\\bar', hasSibling), '**/bar'); + } assert.strictEqual(glob.match(expr, 'foo/foo', hasSibling), null); assert.strictEqual(glob.match(expr, 'foo.js', hasSibling), '**/*.js'); assert.strictEqual(glob.match(expr, 'bar.js', hasSibling), null); @@ -768,7 +774,7 @@ suite('Glob', () => { let expr = { '**/*.js': { when: '$(basename).ts' } }; let siblings = ['foo.ts', 'foo.js']; - let hasSibling = name => siblings.indexOf(name) !== -1; + let hasSibling = (name: string) => siblings.indexOf(name) !== -1; assert.strictEqual(glob.parse(expr)('bar/baz.js', 'baz.js', hasSibling), null); assert.strictEqual(glob.parse(expr)('bar/foo.js', 'foo.js', hasSibling), '**/*.js'); @@ -812,7 +818,7 @@ suite('Glob', () => { ]); const siblings = ['baz', 'baz.zip', 'nope']; - const hasSibling = name => siblings.indexOf(name) !== -1; + const hasSibling = (name: string) => siblings.indexOf(name) !== -1; testOptimizationForBasenames({ '**/foo/**': { when: '$(basename).zip' }, '**/bar/**': true @@ -918,7 +924,7 @@ suite('Glob', () => { ]); const siblings = ['baz', 'baz.zip', 'nope']; - let hasSibling = name => siblings.indexOf(name) !== -1; + let hasSibling = (name: string) => siblings.indexOf(name) !== -1; testOptimizationForPaths({ '**/foo/123/**': { when: '$(basename).zip' }, '**/bar/123/**': true @@ -948,14 +954,14 @@ suite('Glob', () => { test('relative pattern - glob star', function () { if (isWindows) { - let p: glob.IRelativePattern = { base: 'C:\\DNXConsoleApp\\foo', pattern: '**/*.cs', pathToRelative: (from, to) => path.relative(from, to) }; + let p: glob.IRelativePattern = { base: 'C:\\DNXConsoleApp\\foo', pattern: '**/*.cs' }; assertGlobMatch(p, 'C:\\DNXConsoleApp\\foo\\Program.cs'); assertGlobMatch(p, 'C:\\DNXConsoleApp\\foo\\bar\\Program.cs'); assertNoGlobMatch(p, 'C:\\DNXConsoleApp\\foo\\Program.ts'); assertNoGlobMatch(p, 'C:\\DNXConsoleApp\\Program.cs'); assertNoGlobMatch(p, 'C:\\other\\DNXConsoleApp\\foo\\Program.ts'); } else { - let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: '**/*.cs', pathToRelative: (from, to) => path.relative(from, to) }; + let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: '**/*.cs' }; assertGlobMatch(p, '/DNXConsoleApp/foo/Program.cs'); assertGlobMatch(p, '/DNXConsoleApp/foo/bar/Program.cs'); assertNoGlobMatch(p, '/DNXConsoleApp/foo/Program.ts'); @@ -966,14 +972,14 @@ suite('Glob', () => { test('relative pattern - single star', function () { if (isWindows) { - let p: glob.IRelativePattern = { base: 'C:\\DNXConsoleApp\\foo', pattern: '*.cs', pathToRelative: (from, to) => path.relative(from, to) }; + let p: glob.IRelativePattern = { base: 'C:\\DNXConsoleApp\\foo', pattern: '*.cs' }; assertGlobMatch(p, 'C:\\DNXConsoleApp\\foo\\Program.cs'); assertNoGlobMatch(p, 'C:\\DNXConsoleApp\\foo\\bar\\Program.cs'); assertNoGlobMatch(p, 'C:\\DNXConsoleApp\\foo\\Program.ts'); assertNoGlobMatch(p, 'C:\\DNXConsoleApp\\Program.cs'); assertNoGlobMatch(p, 'C:\\other\\DNXConsoleApp\\foo\\Program.ts'); } else { - let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: '*.cs', pathToRelative: (from, to) => path.relative(from, to) }; + let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: '*.cs' }; assertGlobMatch(p, '/DNXConsoleApp/foo/Program.cs'); assertNoGlobMatch(p, '/DNXConsoleApp/foo/bar/Program.cs'); assertNoGlobMatch(p, '/DNXConsoleApp/foo/Program.ts'); @@ -984,11 +990,11 @@ suite('Glob', () => { test('relative pattern - single star with path', function () { if (isWindows) { - let p: glob.IRelativePattern = { base: 'C:\\DNXConsoleApp\\foo', pattern: 'something/*.cs', pathToRelative: (from, to) => path.relative(from, to) }; + let p: glob.IRelativePattern = { base: 'C:\\DNXConsoleApp\\foo', pattern: 'something/*.cs' }; assertGlobMatch(p, 'C:\\DNXConsoleApp\\foo\\something\\Program.cs'); assertNoGlobMatch(p, 'C:\\DNXConsoleApp\\foo\\Program.cs'); } else { - let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: 'something/*.cs', pathToRelative: (from, to) => path.relative(from, to) }; + let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: 'something/*.cs' }; assertGlobMatch(p, '/DNXConsoleApp/foo/something/Program.cs'); assertNoGlobMatch(p, '/DNXConsoleApp/foo/Program.cs'); } @@ -1000,11 +1006,11 @@ suite('Glob', () => { test('relative pattern - #57475', function () { if (isWindows) { - let p: glob.IRelativePattern = { base: 'C:\\DNXConsoleApp\\foo', pattern: 'styles/style.css', pathToRelative: (from, to) => path.relative(from, to) }; + let p: glob.IRelativePattern = { base: 'C:\\DNXConsoleApp\\foo', pattern: 'styles/style.css' }; assertGlobMatch(p, 'C:\\DNXConsoleApp\\foo\\styles\\style.css'); assertNoGlobMatch(p, 'C:\\DNXConsoleApp\\foo\\Program.cs'); } else { - let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: 'styles/style.css', pathToRelative: (from, to) => path.relative(from, to) }; + let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: 'styles/style.css' }; assertGlobMatch(p, '/DNXConsoleApp/foo/styles/style.css'); assertNoGlobMatch(p, '/DNXConsoleApp/foo/Program.cs'); } diff --git a/src/vs/base/test/node/id.test.ts b/src/vs/base/test/node/id.test.ts index 319edca07f9..637afa5b550 100644 --- a/src/vs/base/test/node/id.test.ts +++ b/src/vs/base/test/node/id.test.ts @@ -3,21 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import * as getmac from 'getmac'; import { getMachineId } from 'vs/base/node/id'; +import { getMac } from 'vs/base/node/macAddress'; suite('ID', () => { - test('getMachineId', () => { + test('getMachineId', function () { + this.timeout(20000); return getMachineId().then(id => { assert.ok(id); }); }); test('getMac', () => { - return new Promise((resolve, reject) => { - getmac.getMac((err, macAddress) => err ? reject(err) : resolve(macAddress)); - }).then(macAddress => { + return getMac().then(macAddress => { assert.ok(/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(macAddress), `Expected a MAC address, got: ${macAddress}`); }); }); diff --git a/src/vs/platform/credentials/test/node/keytar.test.ts b/src/vs/base/test/node/keytar.test.ts similarity index 100% rename from src/vs/platform/credentials/test/node/keytar.test.ts rename to src/vs/base/test/node/keytar.test.ts diff --git a/src/vs/base/test/node/pfs.test.ts b/src/vs/base/test/node/pfs.test.ts deleted file mode 100644 index 6c107274a7d..00000000000 --- a/src/vs/base/test/node/pfs.test.ts +++ /dev/null @@ -1,155 +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 * as assert from 'assert'; -import * as os from 'os'; - -import * as path from 'path'; -import * as fs from 'fs'; - -import * as uuid from 'vs/base/common/uuid'; -import * as pfs from 'vs/base/node/pfs'; -import { timeout } from 'vs/base/common/async'; - -suite('PFS', () => { - - test('writeFile', () => { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'pfs', id); - const testFile = path.join(newDir, 'writefile.txt'); - - return pfs.mkdirp(newDir, 493).then(() => { - assert.ok(fs.existsSync(newDir)); - - return pfs.writeFile(testFile, 'Hello World', null!).then(() => { - assert.equal(fs.readFileSync(testFile), 'Hello World'); - - return pfs.del(parentDir, os.tmpdir()); - }); - }); - }); - - test('writeFile - parallel write on different files works', function () { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'pfs', id); - const testFile1 = path.join(newDir, 'writefile1.txt'); - const testFile2 = path.join(newDir, 'writefile2.txt'); - const testFile3 = path.join(newDir, 'writefile3.txt'); - const testFile4 = path.join(newDir, 'writefile4.txt'); - const testFile5 = path.join(newDir, 'writefile5.txt'); - - return pfs.mkdirp(newDir, 493).then(() => { - assert.ok(fs.existsSync(newDir)); - - return Promise.all([ - pfs.writeFile(testFile1, 'Hello World 1', null!), - pfs.writeFile(testFile2, 'Hello World 2', null!), - pfs.writeFile(testFile3, 'Hello World 3', null!), - pfs.writeFile(testFile4, 'Hello World 4', null!), - pfs.writeFile(testFile5, 'Hello World 5', null!) - ]).then(() => { - assert.equal(fs.readFileSync(testFile1), 'Hello World 1'); - assert.equal(fs.readFileSync(testFile2), 'Hello World 2'); - assert.equal(fs.readFileSync(testFile3), 'Hello World 3'); - assert.equal(fs.readFileSync(testFile4), 'Hello World 4'); - assert.equal(fs.readFileSync(testFile5), 'Hello World 5'); - - return pfs.del(parentDir, os.tmpdir()); - }); - }); - }); - - test('writeFile - parallel write on same files works and is sequentalized', function () { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'pfs', id); - const testFile = path.join(newDir, 'writefile.txt'); - - return pfs.mkdirp(newDir, 493).then(() => { - assert.ok(fs.existsSync(newDir)); - - return Promise.all([ - pfs.writeFile(testFile, 'Hello World 1', undefined), - pfs.writeFile(testFile, 'Hello World 2', undefined), - timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 3', undefined)), - pfs.writeFile(testFile, 'Hello World 4', undefined), - timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 5', undefined)) - ]).then(() => { - assert.equal(fs.readFileSync(testFile), 'Hello World 5'); - - return pfs.del(parentDir, os.tmpdir()); - }); - }); - }); - - test('rimraf - simple', function () { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - return pfs.mkdirp(newDir, 493).then(() => { - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); - - return pfs.rimraf(newDir).then(() => { - assert.ok(!fs.existsSync(newDir)); - }); - }); - }); - - test('rimraf - recursive folder structure', function () { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - return pfs.mkdirp(newDir, 493).then(() => { - fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); - fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); - - fs.mkdirSync(path.join(newDir, 'somefolder')); - fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); - - return pfs.rimraf(newDir).then(() => { - assert.ok(!fs.existsSync(newDir)); - }); - }); - }); - - test('unlinkIgnoreError', function () { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - return pfs.mkdirp(newDir, 493).then(() => { - return pfs.unlinkIgnoreError(path.join(newDir, 'foo')).then(() => { - - return pfs.del(parentDir, os.tmpdir()); - }, error => { - assert.fail(error); - - return Promise.reject(error); - }); - }); - }); - - test('moveIgnoreError', function () { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'extfs', id); - - return pfs.mkdirp(newDir, 493).then(() => { - return pfs.renameIgnoreError(path.join(newDir, 'foo'), path.join(newDir, 'bar')).then(() => { - - return pfs.del(parentDir, os.tmpdir()); - }, error => { - assert.fail(error); - - return Promise.reject(error); - }); - }); - }); -}); diff --git a/src/vs/base/test/node/extfs/fixtures/examples/company.jxs b/src/vs/base/test/node/pfs/fixtures/examples/company.jxs similarity index 100% rename from src/vs/base/test/node/extfs/fixtures/examples/company.jxs rename to src/vs/base/test/node/pfs/fixtures/examples/company.jxs diff --git a/src/vs/base/test/node/extfs/fixtures/examples/conway.jxs b/src/vs/base/test/node/pfs/fixtures/examples/conway.jxs similarity index 100% rename from src/vs/base/test/node/extfs/fixtures/examples/conway.jxs rename to src/vs/base/test/node/pfs/fixtures/examples/conway.jxs diff --git a/src/vs/base/test/node/extfs/fixtures/examples/employee.jxs b/src/vs/base/test/node/pfs/fixtures/examples/employee.jxs similarity index 100% rename from src/vs/base/test/node/extfs/fixtures/examples/employee.jxs rename to src/vs/base/test/node/pfs/fixtures/examples/employee.jxs diff --git a/src/vs/base/test/node/extfs/fixtures/examples/small.jxs b/src/vs/base/test/node/pfs/fixtures/examples/small.jxs similarity index 100% rename from src/vs/base/test/node/extfs/fixtures/examples/small.jxs rename to src/vs/base/test/node/pfs/fixtures/examples/small.jxs diff --git a/src/vs/base/test/node/extfs/fixtures/index.html b/src/vs/base/test/node/pfs/fixtures/index.html similarity index 100% rename from src/vs/base/test/node/extfs/fixtures/index.html rename to src/vs/base/test/node/pfs/fixtures/index.html diff --git a/src/vs/base/test/node/extfs/fixtures/site.css b/src/vs/base/test/node/pfs/fixtures/site.css similarity index 100% rename from src/vs/base/test/node/extfs/fixtures/site.css rename to src/vs/base/test/node/pfs/fixtures/site.css diff --git a/src/vs/base/test/node/pfs/pfs.test.ts b/src/vs/base/test/node/pfs/pfs.test.ts new file mode 100644 index 00000000000..060913bbe72 --- /dev/null +++ b/src/vs/base/test/node/pfs/pfs.test.ts @@ -0,0 +1,638 @@ +/*--------------------------------------------------------------------------------------------- + * 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 os from 'os'; +import * as path from 'vs/base/common/path'; +import * as fs from 'fs'; +import { Readable } from 'stream'; +import * as uuid from 'vs/base/common/uuid'; +import * as pfs from 'vs/base/node/pfs'; +import { timeout } from 'vs/base/common/async'; +import { getPathFromAmdModule } from 'vs/base/common/amd'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { isWindows, isLinux } from 'vs/base/common/platform'; +import { canNormalize } from 'vs/base/common/normalization'; +import { VSBuffer } from 'vs/base/common/buffer'; +import { join } from 'path'; + +const chunkSize = 64 * 1024; +const readError = 'Error while reading'; +function toReadable(value: string, throwError?: boolean): Readable { + const totalChunks = Math.ceil(value.length / chunkSize); + const stringChunks: string[] = []; + + for (let i = 0, j = 0; i < totalChunks; ++i, j += chunkSize) { + stringChunks[i] = value.substr(j, chunkSize); + } + + let counter = 0; + return new Readable({ + read: function () { + if (throwError) { + this.emit('error', new Error(readError)); + } + + let res!: string; + let canPush = true; + while (canPush && (res = stringChunks[counter++])) { + canPush = this.push(res); + } + + // EOS + if (!res) { + this.push(null); + } + }, + encoding: 'utf8' + }); +} + +suite('PFS', () => { + + test('writeFile', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + const testFile = path.join(newDir, 'writefile.txt'); + + await pfs.mkdirp(newDir, 493); + assert.ok(fs.existsSync(newDir)); + + await pfs.writeFile(testFile, 'Hello World', (null!)); + assert.equal(fs.readFileSync(testFile), 'Hello World'); + + await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + }); + + test('writeFile - parallel write on different files works', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + const testFile1 = path.join(newDir, 'writefile1.txt'); + const testFile2 = path.join(newDir, 'writefile2.txt'); + const testFile3 = path.join(newDir, 'writefile3.txt'); + const testFile4 = path.join(newDir, 'writefile4.txt'); + const testFile5 = path.join(newDir, 'writefile5.txt'); + + await pfs.mkdirp(newDir, 493); + assert.ok(fs.existsSync(newDir)); + + await Promise.all([ + pfs.writeFile(testFile1, 'Hello World 1', (null!)), + pfs.writeFile(testFile2, 'Hello World 2', (null!)), + pfs.writeFile(testFile3, 'Hello World 3', (null!)), + pfs.writeFile(testFile4, 'Hello World 4', (null!)), + pfs.writeFile(testFile5, 'Hello World 5', (null!)) + ]); + assert.equal(fs.readFileSync(testFile1), 'Hello World 1'); + assert.equal(fs.readFileSync(testFile2), 'Hello World 2'); + assert.equal(fs.readFileSync(testFile3), 'Hello World 3'); + assert.equal(fs.readFileSync(testFile4), 'Hello World 4'); + assert.equal(fs.readFileSync(testFile5), 'Hello World 5'); + + await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + }); + + test('writeFile - parallel write on same files works and is sequentalized', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + const testFile = path.join(newDir, 'writefile.txt'); + + await pfs.mkdirp(newDir, 493); + assert.ok(fs.existsSync(newDir)); + + await Promise.all([ + pfs.writeFile(testFile, 'Hello World 1', undefined), + pfs.writeFile(testFile, 'Hello World 2', undefined), + timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 3', undefined)), + pfs.writeFile(testFile, 'Hello World 4', undefined), + timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 5', undefined)) + ]); + assert.equal(fs.readFileSync(testFile), 'Hello World 5'); + + await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + }); + + test('rimraf - simple - unlink', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + await pfs.mkdirp(newDir, 493); + fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + + await pfs.rimraf(newDir); + assert.ok(!fs.existsSync(newDir)); + }); + + test('rimraf - simple - move', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + await pfs.mkdirp(newDir, 493); + fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + + await pfs.rimraf(newDir, pfs.RimRafMode.MOVE); + assert.ok(!fs.existsSync(newDir)); + }); + + test('rimraf - recursive folder structure - unlink', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + await pfs.mkdirp(newDir, 493); + fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + fs.mkdirSync(path.join(newDir, 'somefolder')); + fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); + + await pfs.rimraf(newDir); + assert.ok(!fs.existsSync(newDir)); + }); + + test('rimraf - recursive folder structure - move', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + await pfs.mkdirp(newDir, 493); + fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + fs.mkdirSync(path.join(newDir, 'somefolder')); + fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); + + await pfs.rimraf(newDir, pfs.RimRafMode.MOVE); + assert.ok(!fs.existsSync(newDir)); + }); + + test('rimraf - simple ends with dot - move', async () => { + const id = `${uuid.generateUuid()}.`; + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + await pfs.mkdirp(newDir, 493); + fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + + await pfs.rimraf(newDir, pfs.RimRafMode.MOVE); + assert.ok(!fs.existsSync(newDir)); + }); + + test('rimraf - simple ends with dot slash/backslash - move', async () => { + const id = `${uuid.generateUuid()}.`; + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + await pfs.mkdirp(newDir, 493); + fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + + await pfs.rimraf(`${newDir}${path.sep}`, pfs.RimRafMode.MOVE); + assert.ok(!fs.existsSync(newDir)); + }); + + test('rimrafSync - swallows file not found error', function () { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + pfs.rimrafSync(newDir); + + assert.ok(!fs.existsSync(newDir)); + }); + + test('rimrafSync - simple', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + await pfs.mkdirp(newDir, 493); + + fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + + pfs.rimrafSync(newDir); + + assert.ok(!fs.existsSync(newDir)); + }); + + test('rimrafSync - recursive folder structure', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + await pfs.mkdirp(newDir, 493); + fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + + fs.mkdirSync(path.join(newDir, 'somefolder')); + fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents'); + + pfs.rimrafSync(newDir); + + assert.ok(!fs.existsSync(newDir)); + }); + + test('moveIgnoreError', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + await pfs.mkdirp(newDir, 493); + try { + await pfs.renameIgnoreError(path.join(newDir, 'foo'), path.join(newDir, 'bar')); + return pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + } + catch (error) { + assert.fail(error); + return Promise.reject(error); + } + }); + + test('copy, move and delete', async () => { + const id = uuid.generateUuid(); + const id2 = uuid.generateUuid(); + const sourceDir = getPathFromAmdModule(require, './fixtures'); + const parentDir = path.join(os.tmpdir(), 'vsctests', 'pfs'); + const targetDir = path.join(parentDir, id); + const targetDir2 = path.join(parentDir, id2); + + await pfs.copy(sourceDir, targetDir); + + assert.ok(fs.existsSync(targetDir)); + assert.ok(fs.existsSync(path.join(targetDir, 'index.html'))); + assert.ok(fs.existsSync(path.join(targetDir, 'site.css'))); + assert.ok(fs.existsSync(path.join(targetDir, 'examples'))); + assert.ok(fs.statSync(path.join(targetDir, 'examples')).isDirectory()); + assert.ok(fs.existsSync(path.join(targetDir, 'examples', 'small.jxs'))); + + await pfs.move(targetDir, targetDir2); + + assert.ok(!fs.existsSync(targetDir)); + assert.ok(fs.existsSync(targetDir2)); + assert.ok(fs.existsSync(path.join(targetDir2, 'index.html'))); + assert.ok(fs.existsSync(path.join(targetDir2, 'site.css'))); + assert.ok(fs.existsSync(path.join(targetDir2, 'examples'))); + assert.ok(fs.statSync(path.join(targetDir2, 'examples')).isDirectory()); + assert.ok(fs.existsSync(path.join(targetDir2, 'examples', 'small.jxs'))); + + await pfs.move(path.join(targetDir2, 'index.html'), path.join(targetDir2, 'index_moved.html')); + + assert.ok(!fs.existsSync(path.join(targetDir2, 'index.html'))); + assert.ok(fs.existsSync(path.join(targetDir2, 'index_moved.html'))); + + await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + + assert.ok(!fs.existsSync(parentDir)); + }); + + test('mkdirp', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + await pfs.mkdirp(newDir, 493); + + assert.ok(fs.existsSync(newDir)); + + return pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + }); + + test('mkdirp cancellation', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + const source = new CancellationTokenSource(); + + const mkdirpPromise = pfs.mkdirp(newDir, 493, source.token); + source.cancel(); + + await mkdirpPromise; + + assert.ok(!fs.existsSync(newDir)); + + return pfs.rimraf(parentDir, pfs.RimRafMode.MOVE); + }); + + test('readDirsInDir', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + + await pfs.mkdirp(newDir, 493); + + fs.mkdirSync(path.join(newDir, 'somefolder1')); + fs.mkdirSync(path.join(newDir, 'somefolder2')); + fs.mkdirSync(path.join(newDir, 'somefolder3')); + fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents'); + fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents'); + + const result = await pfs.readDirsInDir(newDir); + assert.equal(result.length, 3); + assert.ok(result.indexOf('somefolder1') !== -1); + assert.ok(result.indexOf('somefolder2') !== -1); + assert.ok(result.indexOf('somefolder3') !== -1); + + await pfs.rimraf(newDir); + }); + + test('stat link', async () => { + if (isWindows) { + return Promise.resolve(); // Symlinks are not the same on win, and we can not create them programitically without admin privileges + } + + const id1 = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id1); + const directory = path.join(parentDir, 'pfs', id1); + + const id2 = uuid.generateUuid(); + const symbolicLink = path.join(parentDir, 'pfs', id2); + + await pfs.mkdirp(directory, 493); + + fs.symlinkSync(directory, symbolicLink); + + let statAndIsLink = await pfs.statLink(directory); + assert.ok(!statAndIsLink!.isSymbolicLink); + + statAndIsLink = await pfs.statLink(symbolicLink); + assert.ok(statAndIsLink!.isSymbolicLink); + + pfs.rimrafSync(directory); + }); + + test('readdir', async () => { + if (canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id, 'öäü'); + + await pfs.mkdirp(newDir, 493); + + assert.ok(fs.existsSync(newDir)); + + const children = await pfs.readdir(path.join(parentDir, 'pfs', id)); + assert.equal(children.some(n => n === 'öäü'), true); // Mac always converts to NFD, so + + await pfs.rimraf(parentDir); + } + }); + + test('readdirWithFileTypes', async () => { + if (canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const testDir = join(parentDir, 'pfs', id); + + const newDir = path.join(testDir, 'öäü'); + await pfs.mkdirp(newDir, 493); + + await pfs.writeFile(join(testDir, 'somefile.txt'), 'contents'); + + assert.ok(fs.existsSync(newDir)); + + const children = await pfs.readdirWithFileTypes(testDir); + + assert.equal(children.some(n => n.name === 'öäü'), true); // Mac always converts to NFD, so + assert.equal(children.some(n => n.isDirectory()), true); + + assert.equal(children.some(n => n.name === 'somefile.txt'), true); + assert.equal(children.some(n => n.isFile()), true); + + await pfs.rimraf(parentDir); + } + }); + + test('writeFile (string)', async () => { + const smallData = 'Hello World'; + const bigData = (new Array(100 * 1024)).join('Large String\n'); + + return testWriteFileAndFlush(smallData, smallData, bigData, bigData); + }); + + test('writeFile (Buffer)', async () => { + const smallData = 'Hello World'; + const bigData = (new Array(100 * 1024)).join('Large String\n'); + + return testWriteFileAndFlush(Buffer.from(smallData), smallData, Buffer.from(bigData), bigData); + }); + + test('writeFile (UInt8Array)', async () => { + const smallData = 'Hello World'; + const bigData = (new Array(100 * 1024)).join('Large String\n'); + + return testWriteFileAndFlush(VSBuffer.fromString(smallData).buffer, smallData, VSBuffer.fromString(bigData).buffer, bigData); + }); + + test('writeFile (stream)', async () => { + const smallData = 'Hello World'; + const bigData = (new Array(100 * 1024)).join('Large String\n'); + + return testWriteFileAndFlush(toReadable(smallData), smallData, toReadable(bigData), bigData); + }); + + async function testWriteFileAndFlush( + smallData: string | Buffer | NodeJS.ReadableStream | Uint8Array, + smallDataValue: string, + bigData: string | Buffer | NodeJS.ReadableStream | Uint8Array, + bigDataValue: string + ): Promise { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + await pfs.mkdirp(newDir, 493); + assert.ok(fs.existsSync(newDir)); + + await pfs.writeFile(testFile, smallData); + assert.equal(fs.readFileSync(testFile), smallDataValue); + + await pfs.writeFile(testFile, bigData); + assert.equal(fs.readFileSync(testFile), bigDataValue); + + await pfs.rimraf(parentDir); + } + + test('writeFile (file stream)', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const sourceFile = getPathFromAmdModule(require, './fixtures/index.html'); + const newDir = path.join(parentDir, 'pfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + await pfs.mkdirp(newDir, 493); + assert.ok(fs.existsSync(newDir)); + + await pfs.writeFile(testFile, fs.createReadStream(sourceFile)); + assert.equal(fs.readFileSync(testFile).toString(), fs.readFileSync(sourceFile).toString()); + + await pfs.rimraf(parentDir); + }); + + test('writeFile (string, error handling)', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + await pfs.mkdirp(newDir, 493); + + assert.ok(fs.existsSync(newDir)); + + fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory! + + let expectedError: Error | undefined; + try { + await pfs.writeFile(testFile, 'Hello World'); + } catch (error) { + expectedError = error; + } + + assert.ok(expectedError); + + await pfs.rimraf(parentDir); + }); + + test('writeFile (stream, error handling EISDIR)', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + await pfs.mkdirp(newDir, 493); + + assert.ok(fs.existsSync(newDir)); + + fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory! + + const readable = toReadable('Hello World'); + + let expectedError: Error | undefined; + try { + await pfs.writeFile(testFile, readable); + } catch (error) { + expectedError = error; + } + + if (!expectedError || (expectedError).code !== 'EISDIR') { + return Promise.reject(new Error('Expected EISDIR error for writing to folder but got: ' + (expectedError ? (expectedError).code : 'no error'))); + } + + // verify that the stream is still consumable (for https://github.com/Microsoft/vscode/issues/42542) + assert.equal(readable.read(), 'Hello World'); + + await pfs.rimraf(parentDir); + }); + + test('writeFile (stream, error handling READERROR)', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + await pfs.mkdirp(newDir, 493); + assert.ok(fs.existsSync(newDir)); + + let expectedError: Error | undefined; + try { + await pfs.writeFile(testFile, toReadable('Hello World', true /* throw error */)); + } catch (error) { + expectedError = error; + } + + if (!expectedError || expectedError.message !== readError) { + return Promise.reject(new Error('Expected error for writing to folder')); + } + + await pfs.rimraf(parentDir); + }); + + test('writeFile (stream, error handling EACCES)', async () => { + if (isLinux) { + return Promise.resolve(); // somehow this test fails on Linux in our TFS builds + } + + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + await pfs.mkdirp(newDir, 493); + + assert.ok(fs.existsSync(newDir)); + + fs.writeFileSync(testFile, ''); + fs.chmodSync(testFile, 33060); // make readonly + + let expectedError: Error | undefined; + try { + await pfs.writeFile(testFile, toReadable('Hello World')); + } catch (error) { + expectedError = error; + } + + if (!expectedError || !((expectedError).code !== 'EACCES' || (expectedError).code !== 'EPERM')) { + return Promise.reject(new Error('Expected EACCES/EPERM error for writing to folder but got: ' + (expectedError ? (expectedError).code : 'no error'))); + } + + await pfs.rimraf(parentDir); + }); + + test('writeFile (file stream, error handling)', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const sourceFile = getPathFromAmdModule(require, './fixtures/index.html'); + const newDir = path.join(parentDir, 'pfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + await pfs.mkdirp(newDir, 493); + + assert.ok(fs.existsSync(newDir)); + + fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory! + + let expectedError: Error | undefined; + try { + await pfs.writeFile(testFile, fs.createReadStream(sourceFile)); + } catch (error) { + expectedError = error; + } + + if (!expectedError) { + return Promise.reject(new Error('Expected error for writing to folder')); + } + + await pfs.rimraf(parentDir); + }); + + test('writeFileSync', async () => { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'pfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + await pfs.mkdirp(newDir, 493); + + assert.ok(fs.existsSync(newDir)); + + pfs.writeFileSync(testFile, 'Hello World'); + assert.equal(fs.readFileSync(testFile), 'Hello World'); + + const largeString = (new Array(100 * 1024)).join('Large String\n'); + + pfs.writeFileSync(testFile, largeString); + assert.equal(fs.readFileSync(testFile), largeString); + + await pfs.rimraf(parentDir); + }); +}); diff --git a/src/vs/base/test/node/stream/fixtures/file.css b/src/vs/base/test/node/stream/fixtures/file.css deleted file mode 100644 index f7b51e752bb..00000000000 --- a/src/vs/base/test/node/stream/fixtures/file.css +++ /dev/null @@ -1,40 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/*---------------------------------------------------------- -The base color for this template is #5c87b2. If you'd like -to use a different color start by replacing all instances of -#5c87b2 with your new color. -----------------------------------------------------------*/ -body -{ - background-color: #5c87b2; - font-size: .75em; - font-family: Segoe UI, Verdana, Helvetica, Sans-Serif; - margin: 8px; - padding: 0; - color: #696969; -} - -h1, h2, h3, h4, h5, h6 -{ - color: #000; - font-size: 40px; - margin: 0px; -} - -textarea -{ - font-family: Consolas -} - -#results -{ - margin-top: 2em; - margin-left: 2em; - color: black; - font-size: medium; -} - diff --git a/src/vs/base/test/node/stream/stream.test.ts b/src/vs/base/test/node/stream/stream.test.ts deleted file mode 100644 index 632787e68bb..00000000000 --- a/src/vs/base/test/node/stream/stream.test.ts +++ /dev/null @@ -1,45 +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 * as assert from 'assert'; - -import * as stream from 'vs/base/node/stream'; -import { getPathFromAmdModule } from 'vs/base/common/amd'; - -suite('Stream', () => { - test('readExactlyByFile - ANSI', function () { - const file = getPathFromAmdModule(require, './fixtures/file.css'); - - return stream.readExactlyByFile(file, 10).then(({ buffer, bytesRead }) => { - assert.equal(bytesRead, 10); - assert.equal(buffer!.toString(), '/*--------'); - }); - }); - - test('readExactlyByFile - empty', function () { - const file = getPathFromAmdModule(require, './fixtures/empty.txt'); - - return stream.readExactlyByFile(file, 10).then(({ bytesRead }) => { - assert.equal(bytesRead, 0); - }); - }); - - test('readToMatchingString - ANSI', function () { - const file = getPathFromAmdModule(require, './fixtures/file.css'); - - return stream.readToMatchingString(file, '\n', 10, 100).then((result: string) => { - // \r may be present on Windows - assert.equal(result.replace('\r', ''), '/*---------------------------------------------------------------------------------------------'); - }); - }); - - test('readToMatchingString - empty', function () { - const file = getPathFromAmdModule(require, './fixtures/empty.txt'); - - return stream.readToMatchingString(file, '\n', 10, 100).then((result: string) => { - assert.equal(result, null); - }); - }); -}); diff --git a/src/vs/base/test/node/testUtils.ts b/src/vs/base/test/node/testUtils.ts new file mode 100644 index 00000000000..452e8ae0768 --- /dev/null +++ b/src/vs/base/test/node/testUtils.ts @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { join } from 'vs/base/common/path'; +import { generateUuid } from 'vs/base/common/uuid'; + +export function getRandomTestPath(tmpdir: string, ...segments: string[]): string { + return join(tmpdir, ...segments, generateUuid()); +} diff --git a/src/vs/base/test/node/utils.ts b/src/vs/base/test/node/utils.ts index 9bc3a59a16d..5ba6f6e2472 100644 --- a/src/vs/base/test/node/utils.ts +++ b/src/vs/base/test/node/utils.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { generateUuid } from 'vs/base/common/uuid'; -import { join } from 'path'; +import { join } from 'vs/base/common/path'; import { tmpdir } from 'os'; -import { mkdirp, del } from 'vs/base/node/pfs'; +import { mkdirp, rimraf, RimRafMode } from 'vs/base/node/pfs'; export interface ITestFileResult { testFile: string; @@ -16,13 +16,13 @@ export interface ITestFileResult { export function testFile(folder: string, file: string): Promise { const id = generateUuid(); const parentDir = join(tmpdir(), 'vsctests', id); - const newDir = join(parentDir, 'config', id); - const testFile = join(newDir, 'config.json'); + const newDir = join(parentDir, folder, id); + const testFile = join(newDir, file); return mkdirp(newDir, 493).then(() => { return { testFile, - cleanUp: () => del(parentDir, tmpdir()) - } as ITestFileResult; + cleanUp: () => rimraf(parentDir, RimRafMode.MOVE) + }; }); } diff --git a/src/vs/base/worker/defaultWorkerFactory.ts b/src/vs/base/worker/defaultWorkerFactory.ts index 30ad9bf632f..c2a7ddc54e6 100644 --- a/src/vs/base/worker/defaultWorkerFactory.ts +++ b/src/vs/base/worker/defaultWorkerFactory.ts @@ -6,7 +6,7 @@ import { globals } from 'vs/base/common/platform'; import { IWorker, IWorkerCallback, IWorkerFactory, logOnceWebWorkerWarning } from 'vs/base/common/worker/simpleWorker'; -function getWorker(workerId: string, label: string): Worker { +function getWorker(workerId: string, label: string): Worker | Promise { // Option for hosts to overwrite the worker script (used in the standalone editor) if (globals.MonacoEnvironment) { if (typeof globals.MonacoEnvironment.getWorker === 'function') { @@ -18,12 +18,34 @@ function getWorker(workerId: string, label: string): Worker { } // ESM-comment-begin if (typeof require === 'function') { - return new Worker(require.toUrl('./' + workerId) + '#' + label); + // check if the JS lives on a different origin + + const workerMain = require.toUrl('./' + workerId); + if (/^(http:)|(https:)|(file:)/.test(workerMain)) { + const currentUrl = String(window.location); + const currentOrigin = currentUrl.substr(0, currentUrl.length - window.location.hash.length - window.location.search.length - window.location.pathname.length); + if (workerMain.substring(0, currentOrigin.length) !== currentOrigin) { + // this is the cross-origin case + // i.e. the webpage is running at a different origin than where the scripts are loaded from + const workerBaseUrl = workerMain.substr(0, workerMain.length - 'vs/base/worker/workerMain.js'.length); + const js = `/*${label}*/self.MonacoEnvironment={baseUrl: '${workerBaseUrl}'};importScripts('${workerMain}');/*${label}*/`; + const url = `data:text/javascript;charset=utf-8,${encodeURIComponent(js)}`; + return new Worker(url); + } + } + return new Worker(workerMain + '#' + label); } // ESM-comment-end throw new Error(`You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker`); } +function isPromiseLike(obj: any): obj is PromiseLike { + if (typeof obj.then === 'function') { + return true; + } + return false; +} + /** * A worker that uses HTML5 web workers so that is has * its own global scope and its own thread. @@ -31,33 +53,41 @@ function getWorker(workerId: string, label: string): Worker { class WebWorker implements IWorker { private id: number; - private worker: Worker | null; + private worker: Promise | null; constructor(moduleId: string, id: number, label: string, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void) { this.id = id; - this.worker = getWorker('workerMain.js', label); - this.postMessage(moduleId); - this.worker.onmessage = function (ev: any) { - onMessageCallback(ev.data); - }; - if (typeof this.worker.addEventListener === 'function') { - this.worker.addEventListener('error', onErrorCallback); + const workerOrPromise = getWorker('workerMain.js', label); + if (isPromiseLike(workerOrPromise)) { + this.worker = workerOrPromise; + } else { + this.worker = Promise.resolve(workerOrPromise); } + this.postMessage(moduleId, []); + this.worker.then((w) => { + w.onmessage = function (ev: any) { + onMessageCallback(ev.data); + }; + (w).onmessageerror = onErrorCallback; + if (typeof w.addEventListener === 'function') { + w.addEventListener('error', onErrorCallback); + } + }); } public getId(): number { return this.id; } - public postMessage(msg: string): void { + public postMessage(message: any, transfer: Transferable[]): void { if (this.worker) { - this.worker.postMessage(msg); + this.worker.then(w => w.postMessage(message, transfer)); } } public dispose(): void { if (this.worker) { - this.worker.terminate(); + this.worker.then(w => w.terminate()); } this.worker = null; } diff --git a/src/vs/code/browser/workbench/workbench.html b/src/vs/code/browser/workbench/workbench.html new file mode 100644 index 00000000000..5b06636edbb --- /dev/null +++ b/src/vs/code/browser/workbench/workbench.html @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/vs/code/browser/workbench/workbench.js b/src/vs/code/browser/workbench/workbench.js new file mode 100644 index 00000000000..65fae7c82df --- /dev/null +++ b/src/vs/code/browser/workbench/workbench.js @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +(function () { + + require.config({ + baseUrl: `${window.location.origin}/out`, + paths: { + 'vscode-textmate': `${window.location.origin}/node_modules/vscode-textmate/release/main`, + 'onigasm-umd': `${window.location.origin}/node_modules/onigasm-umd/release/main`, + 'xterm': `${window.location.origin}/node_modules/xterm/lib/xterm.js`, + 'xterm-addon-search': `${window.location.origin}/node_modules/xterm-addon-search/lib/xterm-addon-search.js`, + 'xterm-addon-web-links': `${window.location.origin}/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`, + 'semver-umd': `${window.location.origin}/node_modules/semver-umd/lib/semver-umd.js`, + } + }); + + require(['vs/workbench/workbench.web.api'], function (api) { + const options = JSON.parse(document.getElementById('vscode-workbench-web-configuration').getAttribute('data-settings')); + + api.create(document.body, options); + }); +})(); \ No newline at end of file diff --git a/src/vs/code/buildfile.js b/src/vs/code/buildfile.js index 1a39a0a0c2c..221bea21443 100644 --- a/src/vs/code/buildfile.js +++ b/src/vs/code/buildfile.js @@ -5,8 +5,9 @@ 'use strict'; function createModuleDescription(name, exclude) { - var result = {}; - var excludes = ['vs/css', 'vs/nls']; + const result = {}; + + let excludes = ['vs/css', 'vs/nls']; result.name = name; if (Array.isArray(exclude) && exclude.length > 0) { excludes = excludes.concat(exclude); diff --git a/src/vs/code/electron-browser/issue/issueReporterMain.ts b/src/vs/code/electron-browser/issue/issueReporterMain.ts index 169de560b50..e6ee71c50f0 100644 --- a/src/vs/code/electron-browser/issue/issueReporterMain.ts +++ b/src/vs/code/electron-browser/issue/issueReporterMain.ts @@ -10,14 +10,13 @@ import { $ } from 'vs/base/browser/dom'; import * as collections from 'vs/base/common/collections'; import * as browser from 'vs/base/browser/browser'; import { escape } from 'vs/base/common/strings'; -import product from 'vs/platform/node/product'; -import pkg from 'vs/platform/node/package'; +import product from 'vs/platform/product/node/product'; +import pkg from 'vs/platform/product/node/package'; import * as os from 'os'; import { debounce } from 'vs/base/common/decorators'; import * as platform from 'vs/base/common/platform'; import { Disposable } from 'vs/base/common/lifecycle'; -import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser'; -import { getDelayedChannel } from 'vs/base/parts/ipc/node/ipc'; +import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc'; import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IWindowConfiguration, IWindowsService } from 'vs/platform/windows/common/windows'; @@ -28,19 +27,22 @@ import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties'; -import { WindowsChannelClient } from 'vs/platform/windows/node/windowsIpc'; +import { WindowsService } from 'vs/platform/windows/electron-browser/windowsService'; +import { MainProcessService, IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; -import { IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel'; +import { IssueReporterModel, IssueReporterData as IssueReporterModelData } from 'vs/code/electron-browser/issue/issueReporterModel'; import { IssueReporterData, IssueReporterStyles, IssueType, ISettingsSearchIssueReporterData, IssueReporterFeatures, IssueReporterExtensionData } from 'vs/platform/issue/common/issue'; import BaseHtml from 'vs/code/electron-browser/issue/issueReporterPage'; -import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; -import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/node/logIpc'; +import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc'; import { ILogService, getLogLevel } from 'vs/platform/log/common/log'; import { OcticonLabel } from 'vs/base/browser/ui/octiconLabel/octiconLabel'; import { normalizeGitHubUrl } from 'vs/code/electron-browser/issue/issueReporterUtil'; import { Button } from 'vs/base/browser/ui/button/button'; +import { withUndefinedAsNull } from 'vs/base/common/types'; +import { SystemInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnosticsService'; +import { SpdLogService } from 'vs/platform/log/node/spdlogService'; -const MAX_URL_LENGTH = platform.isWindows ? 2081 : 5400; +const MAX_URL_LENGTH = 2045; interface SearchResult { html_url: string; @@ -58,33 +60,37 @@ export function startup(configuration: IssueReporterConfiguration) { const issueReporter = new IssueReporter(configuration); issueReporter.render(); document.body.style.display = 'block'; + issueReporter.setInitialFocus(); } export class IssueReporter extends Disposable { - private environmentService: IEnvironmentService; - private telemetryService: ITelemetryService; - private logService: ILogService; - private issueReporterModel: IssueReporterModel; + private environmentService!: IEnvironmentService; + private telemetryService!: ITelemetryService; + private logService!: ILogService; + private readonly issueReporterModel: IssueReporterModel; private numberOfSearchResultsDisplayed = 0; private receivedSystemInfo = false; private receivedPerformanceInfo = false; private shouldQueueSearch = false; private hasBeenSubmitted = false; - private previewButton: Button; + private readonly previewButton!: Button; constructor(configuration: IssueReporterConfiguration) { super(); this.initServices(configuration); + const isSnap = process.platform === 'linux' && process.env.SNAP && process.env.SNAP_REVISION; this.issueReporterModel = new IssueReporterModel({ issueType: configuration.data.issueType || IssueType.Bug, versionInfo: { vscodeVersion: `${pkg.name} ${pkg.version} (${product.commit || 'Commit unknown'}, ${product.date || 'Date unknown'})`, - os: `${os.type()} ${os.arch()} ${os.release()}` + os: `${os.type()} ${os.arch()} ${os.release()}${isSnap ? ' snap' : ''}` }, extensionsDisabled: !!this.environmentService.disableExtensions, + fileOnExtension: configuration.data.extensionId ? true : undefined, + selectedExtension: configuration.data.extensionId ? configuration.data.enabledExtensions.filter(extension => extension.id === configuration.data.extensionId)[0] : undefined }); const issueReporterElement = this.getElementById('issue-reporter'); @@ -92,7 +98,7 @@ export class IssueReporter extends Disposable { this.previewButton = new Button(issueReporterElement); } - ipcRenderer.on('vscode:issuePerformanceInfoResponse', (_, info) => { + ipcRenderer.on('vscode:issuePerformanceInfoResponse', (_: unknown, info: Partial) => { this.logService.trace('issueReporter: Received performance data'); this.issueReporterModel.update(info); this.receivedPerformanceInfo = true; @@ -103,7 +109,7 @@ export class IssueReporter extends Disposable { this.updatePreviewButtonState(); }); - ipcRenderer.on('vscode:issueSystemInfoResponse', (_, info) => { + ipcRenderer.on('vscode:issueSystemInfoResponse', (_: unknown, info: SystemInfo) => { this.logService.trace('issueReporter: Received system data'); this.issueReporterModel.update({ systemInfo: info }); this.receivedSystemInfo = true; @@ -137,6 +143,21 @@ export class IssueReporter extends Disposable { this.renderBlocks(); } + setInitialFocus() { + const { fileOnExtension } = this.issueReporterModel.getData(); + if (fileOnExtension) { + const issueTitle = document.getElementById('issue-title'); + if (issueTitle) { + issueTitle.focus(); + } + } else { + const issueType = document.getElementById('issue-type'); + if (issueType) { + issueType.focus(); + } + } + } + private applyZoom(zoomLevel: number) { webFrame.setZoomLevel(zoomLevel); browser.setZoomFactor(webFrame.getZoomFactor()); @@ -211,7 +232,7 @@ export class IssueReporter extends Disposable { styleTag.innerHTML = content.join('\n'); document.head.appendChild(styleTag); - document.body.style.color = styles.color || null; + document.body.style.color = withUndefinedAsNull(styles.color); } private handleExtensionData(extensions: IssueReporterExtensionData[]) { @@ -273,14 +294,14 @@ export class IssueReporter extends Disposable { private initServices(configuration: IWindowConfiguration): void { const serviceCollection = new ServiceCollection(); - const mainProcessClient = new ElectronIPCClient(String(`window${configuration.windowId}`)); + const mainProcessService = new MainProcessService(configuration.windowId); + serviceCollection.set(IMainProcessService, mainProcessService); - const windowsChannel = mainProcessClient.getChannel('windows'); - serviceCollection.set(IWindowsService, new WindowsChannelClient(windowsChannel)); + serviceCollection.set(IWindowsService, new WindowsService(mainProcessService)); this.environmentService = new EnvironmentService(configuration, configuration.execPath); - const logService = createSpdLogService(`issuereporter${configuration.windowId}`, getLogLevel(this.environmentService), this.environmentService.logsPath); - const logLevelClient = new LogLevelSetterChannelClient(mainProcessClient.getChannel('loglevel')); + const logService = new SpdLogService(`issuereporter${configuration.windowId}`, this.environmentService.logsPath, getLogLevel(this.environmentService)); + const logLevelClient = new LogLevelSetterChannelClient(mainProcessService.getChannel('loglevel')); this.logService = new FollowerLogService(logLevelClient, logService); const sharedProcess = (serviceCollection.get(IWindowsService)).whenSharedProcessReady() @@ -291,7 +312,7 @@ export class IssueReporter extends Disposable { const channel = getDelayedChannel(sharedProcess.then(c => c.getChannel('telemetryAppender'))); const appender = combinedAppender(new TelemetryAppenderClient(channel), new LogAppender(logService)); const commonProperties = resolveCommonProperties(product.commit || 'Commit unknown', pkg.version, configuration.machineId, this.environmentService.installSourcePath); - const piiPaths = [this.environmentService.appRoot, this.environmentService.extensionsPath]; + const piiPaths = this.environmentService.extensionsPath ? [this.environmentService.appRoot, this.environmentService.extensionsPath] : [this.environmentService.appRoot]; const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths }; const telemetryService = instantiationService.createInstance(TelemetryService, config); @@ -311,10 +332,11 @@ export class IssueReporter extends Disposable { ipcRenderer.send('vscode:issuePerformanceInfoRequest'); } this.updatePreviewButtonState(); + this.setSourceOptions(); this.render(); }); - ['includeSystemInfo', 'includeProcessInfo', 'includeWorkspaceInfo', 'includeExtensions', 'includeSearchedExtensions', 'includeSettingsSearchDetails'].forEach(elementId => { + (['includeSystemInfo', 'includeProcessInfo', 'includeWorkspaceInfo', 'includeExtensions', 'includeSearchedExtensions', 'includeSettingsSearchDetails'] as const).forEach(elementId => { this.addEventListener(elementId, 'click', (event: Event) => { event.stopPropagation(); this.issueReporterModel.update({ [elementId]: !this.issueReporterModel.getData()[elementId] }); @@ -324,7 +346,7 @@ export class IssueReporter extends Disposable { const showInfoElements = document.getElementsByClassName('showInfo'); for (let i = 0; i < showInfoElements.length; i++) { const showInfo = showInfoElements.item(i); - showInfo!.addEventListener('click', (e) => { + showInfo!.addEventListener('click', (e: MouseEvent) => { e.preventDefault(); const label = (e.target); if (label) { @@ -342,8 +364,20 @@ export class IssueReporter extends Disposable { } this.addEventListener('issue-source', 'change', (e: Event) => { - const fileOnExtension = JSON.parse((e.target).value); - this.issueReporterModel.update({ fileOnExtension: fileOnExtension, includeExtensions: !fileOnExtension }); + const value = (e.target).value; + const problemSourceHelpText = this.getElementById('problem-source-help-text')!; + if (value === '') { + this.issueReporterModel.update({ fileOnExtension: undefined }); + show(problemSourceHelpText); + this.clearSearchResults(); + this.render(); + return; + } else { + hide(problemSourceHelpText); + } + + const fileOnExtension = JSON.parse(value); + this.issueReporterModel.update({ fileOnExtension: fileOnExtension }); this.render(); const title = (this.getElementById('issue-title')).value; @@ -360,7 +394,7 @@ export class IssueReporter extends Disposable { this.issueReporterModel.update({ issueDescription }); // Only search for extension issues on title change - if (!this.issueReporterModel.fileOnExtension()) { + if (this.issueReporterModel.fileOnExtension() === false) { const title = (this.getElementById('issue-title')).value; this.searchVSCodeIssues(title, issueDescription); } @@ -375,7 +409,12 @@ export class IssueReporter extends Disposable { hide(lengthValidationMessage); } - if (this.issueReporterModel.fileOnExtension()) { + const fileOnExtension = this.issueReporterModel.fileOnExtension(); + if (fileOnExtension === undefined) { + return; + } + + if (fileOnExtension) { this.searchExtensionIssues(title); } else { const description = this.issueReporterModel.getData().issueDescription; @@ -401,11 +440,11 @@ export class IssueReporter extends Disposable { } }); - document.onkeydown = (e: KeyboardEvent) => { + document.onkeydown = async (e: KeyboardEvent) => { const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey; // Cmd/Ctrl+Enter previews issue and closes window if (cmdOrCtrlKey && e.keyCode === 13) { - if (this.createIssue()) { + if (await this.createIssue()) { ipcRenderer.send('vscode:closeIssueReporter'); } } @@ -637,12 +676,14 @@ export class IssueReporter extends Disposable { private logSearchError(error: Error) { this.logService.warn('issueReporter#search ', error.message); - /* __GDPR__ - "issueReporterSearchError" : { - "message" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" } - } - */ - this.telemetryService.publicLog('issueReporterSearchError', { message: error.message }); + type IssueReporterSearchErrorClassification = { + message: { classification: 'CallstackOrException', purpose: 'PerformanceAndHealth' } + }; + + type IssueReporterSearchError = { + message: string; + }; + this.telemetryService.publicLog2('issueReporterSearchError', { message: error.message }); } private setUpTypes(): void { @@ -662,6 +703,49 @@ export class IssueReporter extends Disposable { } typeSelect.value = issueType.toString(); + + this.setSourceOptions(); + } + + private makeOption(value: string, description: string, disabled: boolean): HTMLOptionElement { + const option: HTMLOptionElement = document.createElement('option'); + option.disabled = disabled; + option.value = value; + option.textContent = description; + + return option; + } + + private setSourceOptions(): void { + const sourceSelect = this.getElementById('issue-source')! as HTMLSelectElement; + const { issueType, fileOnExtension } = this.issueReporterModel.getData(); + let selected = sourceSelect.selectedIndex; + if (selected === -1 && fileOnExtension !== undefined) { + selected = fileOnExtension ? 2 : 1; + } + + sourceSelect.innerHTML = ''; + if (issueType === IssueType.FeatureRequest) { + sourceSelect.append(...[ + this.makeOption('', localize('selectSource', "Select source"), true), + this.makeOption('false', localize('vscode', "Visual Studio Code"), false), + this.makeOption('true', localize('extension', "An extension"), false) + ]); + } else { + sourceSelect.append(...[ + this.makeOption('', localize('selectSource', "Select source"), true), + this.makeOption('false', localize('vscode', "Visual Studio Code"), false), + this.makeOption('true', localize('extension', "An extension"), false), + this.makeOption('', localize('unknown', "Don't Know"), false) + ]); + } + + if (selected !== -1 && selected < sourceSelect.options.length) { + sourceSelect.selectedIndex = selected; + } else { + sourceSelect.selectedIndex = 0; + hide(this.getElementById('problem-source-help-text')); + } } private renderBlocks(): void { @@ -676,7 +760,6 @@ export class IssueReporter extends Disposable { const settingsSearchResultsBlock = document.querySelector('.block-settingsSearchResults'); const problemSource = this.getElementById('problem-source')!; - const problemSourceHelpText = this.getElementById('problem-source-help-text')!; const descriptionTitle = this.getElementById('issue-description-label')!; const descriptionSubtitle = this.getElementById('issue-description-subtitle')!; const extensionSelector = this.getElementById('extension-selection')!; @@ -690,7 +773,6 @@ export class IssueReporter extends Disposable { hide(searchedExtensionsBlock); hide(settingsSearchResultsBlock); hide(problemSource); - hide(problemSourceHelpText); hide(extensionSelector); if (issueType === IssueType.Bug) { @@ -702,7 +784,6 @@ export class IssueReporter extends Disposable { show(extensionSelector); } else { show(extensionsBlock); - show(problemSourceHelpText); } descriptionTitle.innerHTML = `${localize('stepsToReproduce', "Steps to Reproduce")} *`; @@ -718,7 +799,6 @@ export class IssueReporter extends Disposable { show(extensionSelector); } else { show(extensionsBlock); - show(problemSourceHelpText); } descriptionTitle.innerHTML = `${localize('stepsToReproduce', "Steps to Reproduce")} *`; @@ -765,7 +845,7 @@ export class IssueReporter extends Disposable { return isValid; } - private createIssue(): boolean { + private async createIssue(): Promise { if (!this.validateInputs()) { // If inputs are invalid, set focus to the first one and add listeners on them // to detect further changes @@ -782,6 +862,10 @@ export class IssueReporter extends Disposable { this.validateInput('description'); }); + this.addEventListener('issue-source', 'change', _ => { + this.validateInput('issue-source'); + }); + if (this.issueReporterModel.fileOnExtension()) { this.addEventListener('extension-selector', 'change', _ => { this.validateInput('extension-selector'); @@ -791,13 +875,15 @@ export class IssueReporter extends Disposable { return false; } - /* __GDPR__ - "issueReporterSubmit" : { - "issueType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "numSimilarIssuesDisplayed" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } - } - */ - this.telemetryService.publicLog('issueReporterSubmit', { issueType: this.issueReporterModel.getData().issueType, numSimilarIssuesDisplayed: this.numberOfSearchResultsDisplayed }); + type IssueReporterSubmitClassification = { + issueType: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; + numSimilarIssuesDisplayed: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; + }; + type IssueReporterSubmitEvent = { + issueType: any; + numSimilarIssuesDisplayed: number; + }; + this.telemetryService.publicLog2('issueReporterSubmit', { issueType: this.issueReporterModel.getData().issueType, numSimilarIssuesDisplayed: this.numberOfSearchResultsDisplayed }); this.hasBeenSubmitted = true; const baseUrl = this.getIssueUrlWithTitle((this.getElementById('issue-title')).value); @@ -805,14 +891,32 @@ export class IssueReporter extends Disposable { let url = baseUrl + `&body=${encodeURIComponent(issueBody)}`; if (url.length > MAX_URL_LENGTH) { - clipboard.writeText(issueBody); - url = baseUrl + `&body=${encodeURIComponent(localize('pasteData', "We have written the needed data into your clipboard because it was too large to send. Please paste."))}`; + try { + url = await this.writeToClipboard(baseUrl, issueBody); + } catch (_) { + return false; + } } ipcRenderer.send('vscode:openExternal', url); return true; } + private async writeToClipboard(baseUrl: string, issueBody: string): Promise { + return new Promise((resolve, reject) => { + ipcRenderer.once('vscode:issueReporterClipboardResponse', (_: unknown, shouldWrite: boolean) => { + if (shouldWrite) { + clipboard.writeText(issueBody); + resolve(baseUrl + `&body=${encodeURIComponent(localize('pasteData', "We have written the needed data into your clipboard because it was too large to send. Please paste."))}`); + } else { + reject(); + } + }); + + ipcRenderer.send('vscode:issueReporterClipboard'); + }); + } + private getExtensionGitHubUrl(): string { let repositoryUrl = ''; const bugsUrl = this.getExtensionBugsUrl(); @@ -840,22 +944,43 @@ export class IssueReporter extends Disposable { return `${repositoryUrl}${queryStringPrefix}title=${encodeURIComponent(issueTitle)}`; } - private updateSystemInfo = (state) => { + private updateSystemInfo(state: IssueReporterModelData) { const target = document.querySelector('.block-system .block-info'); if (target) { - let tableHtml = ''; - Object.keys(state.systemInfo).forEach(k => { - const data = typeof state.systemInfo[k] === 'object' - ? Object.keys(state.systemInfo[k]).map(key => `${key}: ${state.systemInfo[k][key]}`).join('
    ') - : state.systemInfo[k]; + const systemInfo = state.systemInfo!; + let renderedData = ` + + + + + + + + +
    CPUs${systemInfo.cpus}
    GPU Status${Object.keys(systemInfo.gpuStatus).map(key => `${key}: ${systemInfo.gpuStatus[key]}`).join('
    ')}
    Load (avg)${systemInfo.load}
    Memory (System)${systemInfo.memory}
    Process Argv${systemInfo.processArgs}
    Screen Reader${systemInfo.screenReader}
    VM${systemInfo.vmHint}
    `; - tableHtml += ` - - ${k} - ${data} - `; + systemInfo.remoteData.forEach(remote => { + if (isRemoteDiagnosticError(remote)) { + renderedData += ` +
    + + + +
    Remote${remote.hostName}
    ${remote.errorMessage}
    `; + } else { + renderedData += ` +
    + + + + + + +
    Remote${remote.hostName}
    OS${remote.machineInfo.os}
    CPUs${remote.machineInfo.cpus}
    Memory (System)${remote.machineInfo.memory}
    VM${remote.machineInfo.vmHint}
    `; + } }); - target.innerHTML = `${tableHtml}
    `; + + target.innerHTML = renderedData; } } @@ -887,10 +1012,15 @@ export class IssueReporter extends Disposable { return 0; }); - const makeOption = (extension: IOption) => ``; + const makeOption = (extension: IOption, selectedExtension?: IssueReporterExtensionData) => { + const selected = selectedExtension && extension.id === selectedExtension.id; + return ``; + }; + const extensionsSelector = this.getElementById('extension-selector'); if (extensionsSelector) { - extensionsSelector.innerHTML = '' + extensionOptions.map(makeOption).join('\n'); + const { selectedExtension } = this.issueReporterModel.getData(); + extensionsSelector.innerHTML = '' + extensionOptions.map(extension => makeOption(extension, selectedExtension)).join('\n'); this.addEventListener('extension-selector', 'change', (e: Event) => { const selectedExtensionId = (e.target).value; @@ -909,14 +1039,14 @@ export class IssueReporter extends Disposable { } } - private updateProcessInfo = (state) => { + private updateProcessInfo(state: IssueReporterModelData) { const target = document.querySelector('.block-process .block-info'); if (target) { target.innerHTML = `${state.processInfo}`; } } - private updateWorkspaceInfo = (state) => { + private updateWorkspaceInfo(state: IssueReporterModelData) { document.querySelector('.block-workspace .block-info code')!.textContent = '\n' + state.workspaceInfo; } @@ -980,11 +1110,7 @@ export class IssueReporter extends Disposable { // Exclude right click if (event.which < 3) { shell.openExternal((event.target).href); - - /* __GDPR__ - "issueReporterViewSimilarIssue" : { } - */ - this.telemetryService.publicLog('issueReporterViewSimilarIssue'); + this.telemetryService.publicLog2('issueReporterViewSimilarIssue'); } } @@ -995,12 +1121,13 @@ export class IssueReporter extends Disposable { } else { const error = new Error(`${elementId} not found.`); this.logService.error(error); - /* __GDPR__ - "issueReporterGetElementError" : { - "message" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" } - } - */ - this.telemetryService.publicLog('issueReporterGetElementError', { message: error.message }); + type IssueReporterGetElementErrorClassification = { + message: { classification: 'CallstackOrException', purpose: 'PerformanceAndHealth' }; + }; + type IssueReporterGetElementErrorEvent = { + message: string; + }; + this.telemetryService.publicLog2('issueReporterGetElementError', { message: error.message }); return undefined; } @@ -1016,9 +1143,13 @@ export class IssueReporter extends Disposable { // helper functions -function hide(el) { - el.classList.add('hidden'); +function hide(el: Element | undefined | null) { + if (el) { + el.classList.add('hidden'); + } } -function show(el) { - el.classList.remove('hidden'); +function show(el: Element | undefined | null) { + if (el) { + el.classList.remove('hidden'); + } } diff --git a/src/vs/code/electron-browser/issue/issueReporterModel.ts b/src/vs/code/electron-browser/issue/issueReporterModel.ts index 72e1a81ff20..c1f78969153 100644 --- a/src/vs/code/electron-browser/issue/issueReporterModel.ts +++ b/src/vs/code/electron-browser/issue/issueReporterModel.ts @@ -5,13 +5,14 @@ import { assign } from 'vs/base/common/objects'; import { IssueType, ISettingSearchResult, IssueReporterExtensionData } from 'vs/platform/issue/common/issue'; +import { SystemInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnosticsService'; export interface IssueReporterData { issueType: IssueType; issueDescription?: string; versionInfo?: any; - systemInfo?: any; + systemInfo?: SystemInfo; processInfo?: any; workspaceInfo?: any; @@ -34,7 +35,7 @@ export interface IssueReporterData { } export class IssueReporterModel { - private _data: IssueReporterData; + private readonly _data: IssueReporterData; constructor(initialData?: Partial) { const defaultData = { @@ -67,17 +68,26 @@ ${this._data.issueDescription} ${this.getExtensionVersion()} VS Code version: ${this._data.versionInfo && this._data.versionInfo.vscodeVersion} OS version: ${this._data.versionInfo && this._data.versionInfo.os} - +${this.getRemoteOSes()} ${this.getInfos()} `; } - fileOnExtension(): boolean { + private getRemoteOSes(): string { + if (this._data.systemInfo && this._data.systemInfo.remoteData.length) { + return this._data.systemInfo.remoteData + .map(remote => isRemoteDiagnosticError(remote) ? remote.errorMessage : `Remote OS version: ${remote.machineInfo.os}`).join('\n') + '\n'; + } + + return ''; + } + + fileOnExtension(): boolean | undefined { const fileOnExtensionSupported = this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue || this._data.issueType === IssueType.FeatureRequest; - return !!(fileOnExtensionSupported && this._data.fileOnExtension); + return fileOnExtensionSupported && this._data.fileOnExtension; } private getExtensionVersion(): string { @@ -121,7 +131,7 @@ ${this.getInfos()} } if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) { - if (this._data.includeExtensions) { + if (!this._data.fileOnExtension && this._data.includeExtensions) { info += this.generateExtensionsMd(); } } @@ -148,13 +158,32 @@ ${this.getInfos()} |---|---| `; - Object.keys(this._data.systemInfo).forEach(k => { - const data = typeof this._data.systemInfo[k] === 'object' - ? Object.keys(this._data.systemInfo[k]).map(key => `${key}: ${this._data.systemInfo[k][key]}`).join('
    ') - : this._data.systemInfo[k]; + if (this._data.systemInfo) { - md += `|${k}|${data}|\n`; - }); + md += `|CPUs|${this._data.systemInfo.cpus}| +|GPU Status|${Object.keys(this._data.systemInfo.gpuStatus).map(key => `${key}: ${this._data.systemInfo!.gpuStatus[key]}`).join('
    ')}| +|Load (avg)|${this._data.systemInfo.load}| +|Memory (System)|${this._data.systemInfo.memory}| +|Process Argv|${this._data.systemInfo.processArgs}| +|Screen Reader|${this._data.systemInfo.screenReader}| +|VM|${this._data.systemInfo.vmHint}|`; + + this._data.systemInfo.remoteData.forEach(remote => { + if (isRemoteDiagnosticError(remote)) { + md += `\n\n${remote.errorMessage}`; + } else { + md += ` + +|Item|Value| +|---|---| +|Remote|${remote.hostName}| +|OS|${remote.machineInfo.os}| +|CPUs|${remote.machineInfo.cpus}| +|Memory (System)|${remote.machineInfo.memory}| +|VM|${remote.machineInfo.vmHint}|`; + } + }); + } md += '\n'; @@ -196,7 +225,7 @@ ${this._data.workspaceInfo}; return 'Extensions: none' + themeExclusionStr; } - let tableHeader = `Extension|Author (truncated)|Version + const tableHeader = `Extension|Author (truncated)|Version ---|---|---`; const table = this._data.enabledNonThemeExtesions.map(e => { return `${e.name}|${e.publisher.substr(0, 3)}|${e.version}`; @@ -226,7 +255,7 @@ Literal matches: ${this._data.filterResultCount}`; return `No fuzzy results`; } - let tableHeader = `Setting|Extension|Score + const tableHeader = `Setting|Extension|Score ---|---|---`; const table = this._data.actualSearchResults.map(setting => { return `${setting.key}|${setting.extensionId}|${String(setting.score).slice(0, 5)}`; diff --git a/src/vs/code/electron-browser/issue/issueReporterPage.ts b/src/vs/code/electron-browser/issue/issueReporterPage.ts index 32619366e7f..63f42d9b960 100644 --- a/src/vs/code/electron-browser/issue/issueReporterPage.ts +++ b/src/vs/code/electron-browser/issue/issueReporterPage.ts @@ -19,12 +19,11 @@ export default (): string => `
    - - + -
    ${escape(localize('disableExtensionsLabelText', "Try to reproduce the problem after {0}. If the problem only reproduces when extensions are active, it is likely an issue with an extension.")) + @@ -64,7 +63,7 @@ export default (): string => `