diff --git a/.editorconfig b/.editorconfig index 1923d410..17d8455e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,3 +6,6 @@ indent_size = 2 charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true + +[*.ts] +max_line_length = 120 diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 0edb556e..132cf2ab 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -4,3 +4,4 @@ # See https://michaelheap.com/git-ignore-rev/ 7728691ea1cddf2fe53db0f007d2ac879b0d54d0 +61707019a996d6c1e39a8abfb4c3d7f6af923cd2 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 37f8434f..58753c9f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -16,12 +16,12 @@ permissions: on: push: - branches: [ main ] + branches: [main] pull_request: # The branches below must be a subset of the branches above - branches: [ main ] + branches: [main] schedule: - - cron: '33 1 * * 5' + - cron: "33 1 * * 5" jobs: analyze: @@ -35,39 +35,39 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'javascript' ] + language: ["javascript"] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://git.io/codeql-language-support steps: - - name: Checkout repository - uses: actions/checkout@v3 + - name: Checkout repository + uses: actions/checkout@v3 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl - # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language + # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language - #- run: | - # make bootstrap - # make release + #- run: | + # make bootstrap + # make release - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9797ade7..b2441e9c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,29 +5,29 @@ permissions: on: push: - branches: [ main ] + branches: [main] pull_request: - branches: [ main ] + branches: [main] workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: install node - uses: actions/setup-node@v3 - with: - node-version: 16 - - name: yarn install - run: yarn install - - name: tsc - run: tsc --noEmit --noErrorTruncation --pretty false + - uses: actions/checkout@v3 + - name: install node + uses: actions/setup-node@v3 + with: + node-version: 16 + - name: yarn install + run: yarn install + - name: tsc + run: tsc --noEmit --noErrorTruncation --pretty false api-check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Check Meson API - run: | - git clone https://github.com/mesonbuild/meson --depth 1 - ./ci/check-meson-api.py + - uses: actions/checkout@v3 + - name: Check Meson API + run: | + git clone https://github.com/mesonbuild/meson --depth 1 + ./ci/check-meson-api.py diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml new file mode 100644 index 00000000..7c75a247 --- /dev/null +++ b/.github/workflows/prettier.yml @@ -0,0 +1,33 @@ +name: Prettier + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref }} + cancel-in-progress: true + +jobs: + prettier: + runs-on: ubuntu-latest + + steps: + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: latest + + - name: Checkout + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + yarn install --immutable --immutable-cache --check-cache + + - name: Check + run: | + yarn run prettier:check diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000..37331ee9 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +yarn --silent lint-staged -r diff --git a/.lintstagedrc.json b/.lintstagedrc.json new file mode 100644 index 00000000..48361326 --- /dev/null +++ b/.lintstagedrc.json @@ -0,0 +1,3 @@ +{ + "*.{js,jsx,ts,tsx,json,css,md,html,yml,yaml}": "prettier --write" +} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..6a3417b8 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +/out/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 9242bc98..46c0a7a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,53 +15,60 @@ ## 1.9.0 -- Automatically configure Intellisense to use compile_commands.json generated - by Meson +- Automatically configure Intellisense to use compile_commands.json generated by + Meson - Meson `tasks.json` entries specifying `target` will now need to include the target's type. E.g. `"target": "relative/path/to/targetname:shared_library"` ## 1.8.1 -- Drop vscode-nls dependency, which was unused and is no longer provided by default +- Drop vscode-nls dependency, which was unused and is no longer provided by + default ## 1.8.0 - Generate `/meson-vscode.env` to be used in `launch.json`'s `envFile` - to run programs using Meson's developper environment. - See https://mesonbuild.com/Commands.html#devenv + to run programs using Meson's developper environment. See + https://mesonbuild.com/Commands.html#devenv ## 1.7.1 -- Track the version of linting tools, so that features of new versions may be used +- Track the version of linting tools, so that features of new versions may be + used ## 1.7.0 -- Add `mesonbuild.debugOptions` configuration option. This allows to inject members into the debug configurations generated by this extension. +- Add `mesonbuild.debugOptions` configuration option. This allows to inject + members into the debug configurations generated by this extension. - Add gcc compiler errors to problem view - Allow opening meson.build files from tree-view - Add button to run configure from the tree-view -- Add setupOptions, for options to pass exclusively to meson setup, but not meson configure +- Add setupOptions, for options to pass exclusively to meson setup, but not + meson configure ## 1.6.0 + - Add highlighting for `add_project_dependencies()` - Add a meson DSL linter framework - Add a meson DSL formatter framework - Add [muon](https://muon.build) as a linting and formatting provider - Add `in` operator - ## 1.5.2 + - Fix highlighting for `structured_sources()` - Add highlighting for `install_symlink()` - Add highlighting for `debug()` -- Remove highlighting for obsolete `getext()` and `find_library()`. These have been deprecated for some time and will result in an error if used. +- Remove highlighting for obsolete `getext()` and `find_library()`. These have + been deprecated for some time and will result in an error if used. - Add highlighting for `unset_variable()`, `install_emptydir()`, and `range()` - ## 1.5.1 + - Add highlighting for the new `structured_sources` function ## 1.5.0 + - Update to the new Meson icon - Initial support for the vscode native testing API - Add support for vscode debug API @@ -73,6 +80,7 @@ - Update various deprecated vscode features and API usage ## 1.4.0 + - Move to the mesonbuild project - syntax highlighting for dictionary literals, continue and break - Bugfix: tests and benchmarks with spaces in their names now work @@ -83,23 +91,28 @@ - Bugifx: Reload view on changes. ## 1.3.0 + - Remove layout=flat from default options - Change default build folder to builddir - Add syntax highlighting for new builtins ## 1.2.0 + - Add support for automatic task provider using `meson introspect` - Add code snippets - Add extension configuration ## 1.1.1 + - Remove configuration for {} as special tokens - Add licensing information ## 1.1.0 + - Add support for toggling comments - Auto-close brackets and strings - Add support for hex literals ## 1.0.0 + - Initial release diff --git a/LICENSE.md b/LICENSE.md index 261eeb9e..957a4b87 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -2,180 +2,169 @@ 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: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) 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 - - (d) 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 - - APPENDIX: How to apply the Apache License to your work. +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: + + (a) You must give any other recipients of the Work or Derivative Works a + copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating + that You changed the files; and + + (c) 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 + + (d) 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 + +APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" @@ -186,16 +175,15 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] +Copyright [yyyy] [name of copyright owner] - 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 +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 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. diff --git a/README.md b/README.md index 2002f36a..50ea8950 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,14 @@ # Meson for VisualStudio Code -This extension provides support for [Meson](http://mesonbuild.com/) in [Visual Studio Code](https://code.visualstudio.com/). -This is entirely based on the grammar found in the [atom extension](https://github.com/TingPing/language-meson) from [Patrick Griffis](https://github.com/TingPing). +This extension provides support for [Meson](http://mesonbuild.com/) in +[Visual Studio Code](https://code.visualstudio.com/). This is entirely based on +the grammar found in the +[atom extension](https://github.com/TingPing/language-meson) from +[Patrick Griffis](https://github.com/TingPing). -Meson logo by @jpakkane, [licensed for use by this project](http://mesonbuild.com/legal.html). -Icons from the [Material Design Icons](https://materialdesignicons.com/) project. +Meson logo by @jpakkane, +[licensed for use by this project](http://mesonbuild.com/legal.html). Icons from +the [Material Design Icons](https://materialdesignicons.com/) project. ## Features @@ -22,5 +26,6 @@ Icons from the [Material Design Icons](https://materialdesignicons.com/) project # New extension ID -If you come from a previous installation, please make sure you are on the **mesonbuild.mesonbuild** extension. -There are 3 variants/versions of this extension on the store, and only that one is released from this repository. +If you come from a previous installation, please make sure you are on the +**mesonbuild.mesonbuild** extension. There are 3 variants/versions of this +extension on the store, and only that one is released from this repository. diff --git a/language-configuration.json b/language-configuration.json index b4c0b8a9..1c7742df 100644 --- a/language-configuration.json +++ b/language-configuration.json @@ -3,69 +3,36 @@ "lineComment": "#" }, "brackets": [ - [ - "[", - "]" - ], - [ - "(", - ")" - ], - [ - "{", - "}" - ] + ["[", "]"], + ["(", ")"], + ["{", "}"] ], "autoClosingPairs": [ { "open": "[", "close": "]", - "notIn": [ - "string", - "comment" - ] + "notIn": ["string", "comment"] }, { "open": "(", "close": ")", - "notIn": [ - "string", - "comment" - ] + "notIn": ["string", "comment"] }, { "open": "{", "close": "}", - "notIn": [ - "string", - "comment" - ] + "notIn": ["string", "comment"] }, { "open": "'", "close": "'", - "notIn": [ - "string", - "comment" - ] + "notIn": ["string", "comment"] } ], "surroundingPairs": [ - [ - "[", - "]" - ], - [ - "(", - ")" - ], - [ - "{", - "}" - ], - [ - "'", - "'" - ] + ["[", "]"], + ["(", ")"], + ["{", "}"], + ["'", "'"] ] } diff --git a/package.json b/package.json index df031324..6d857ad1 100644 --- a/package.json +++ b/package.json @@ -331,14 +331,22 @@ ] }, "scripts": { - "vscode:prepublish": "npm run compile", "compile": "tsc -p ./", + "postinstall": "husky install", + "prettier:check": "prettier --check **.md **.ts **.yml **.json", + "vscode:prepublish": "npm run compile", "watch": "tsc -watch -p ./" }, "devDependencies": { "@types/node": "^16.11.7", "@types/vscode": "^1.1.59", + "husky": "^8.0.3", + "lint-staged": "^14.0.1", + "prettier": "^3.0.3", "typescript": "^4.4.4" }, - "dependencies": {} + "dependencies": {}, + "prettier": { + "proseWrap": "always" + } } diff --git a/src/configprovider.ts b/src/configprovider.ts index ef54ed2c..e13345fe 100644 --- a/src/configprovider.ts +++ b/src/configprovider.ts @@ -1,49 +1,44 @@ import * as vscode from "vscode"; -import * as path from 'path'; -import { - getMesonTargets -} from "./introspection" -import { - Target -} from "./types" -import { - extensionConfiguration, - getTargetName -} from "./utils" +import * as path from "path"; +import { getMesonTargets } from "./introspection"; +import { Target } from "./types"; +import { extensionConfiguration, getTargetName } from "./utils"; export enum MIModes { - lldb = 'lldb', - gdb = 'gdb', + lldb = "lldb", + gdb = "gdb", } export class DebugConfigurationProvider implements vscode.DebugConfigurationProvider { private path: string; constructor(path: string) { - this.path = path + this.path = path; } async createBaseDebugConfiguration(target: Target): Promise { const targetName = await getTargetName(target); return { - type: 'cppdbg', + type: "cppdbg", name: `Debug ${target.name}`, - request: 'launch', + request: "launch", cwd: path.dirname(this.path), program: target.filename[0], args: [], - preLaunchTask: `Meson: Build ${targetName}` + preLaunchTask: `Meson: Build ${targetName}`, }; } async createGDBDebugConfiguration(target: Target): Promise { let debugConfig = await this.createBaseDebugConfiguration(target); debugConfig["MIMode"] = MIModes.gdb; - debugConfig["setupCommands"] = [{ - description: 'Enable pretty-printing for gdb', - text: '-enable-pretty-printing', - ignoreFailures: true - }]; + debugConfig["setupCommands"] = [ + { + description: "Enable pretty-printing for gdb", + text: "-enable-pretty-printing", + ignoreFailures: true, + }, + ]; return debugConfig; } @@ -55,44 +50,54 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv async createMSVCDebugConfiguration(target: Target): Promise { let debugConfig = await this.createBaseDebugConfiguration(target); - debugConfig.type = 'cppvsdbg'; + debugConfig.type = "cppvsdbg"; return debugConfig; } - async provideDebugConfigurations(folder: vscode.WorkspaceFolder | undefined, token?: vscode.CancellationToken): Promise { + async provideDebugConfigurations( + folder: vscode.WorkspaceFolder | undefined, + token?: vscode.CancellationToken, + ): Promise { let targets = await getMesonTargets(this.path); let configDebugOptions = extensionConfiguration("debugOptions"); - const executables = targets.filter(target => target.type == "executable"); + const executables = targets.filter((target) => target.type == "executable"); let ret: vscode.DebugConfiguration[] = []; for (const target of executables) { - if (!target.target_sources?.some(source => ['cpp', 'c'].includes(source.language))) { + if (!target.target_sources?.some((source) => ["cpp", "c"].includes(source.language))) { continue; } let debugConfiguration = null; - if (target.target_sources.some(source => ['cl'].includes(source.compiler[0]))) { + if (target.target_sources.some((source) => ["cl"].includes(source.compiler[0]))) { debugConfiguration = await this.createMSVCDebugConfiguration(target); - } else if (target.target_sources.some(source => ['cc', 'clang'].includes(source.compiler[0]))) { + } else if (target.target_sources.some((source) => ["cc", "clang"].includes(source.compiler[0]))) { debugConfiguration = await this.createLLDBDebugConfiguration(target); } else { debugConfiguration = await this.createGDBDebugConfiguration(target); } - ret.push({ ...configDebugOptions, ...debugConfiguration }) + ret.push({ ...configDebugOptions, ...debugConfiguration }); } return ret; } - resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, debugConfiguration: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult { - return debugConfiguration + resolveDebugConfiguration( + folder: vscode.WorkspaceFolder | undefined, + debugConfiguration: vscode.DebugConfiguration, + token?: vscode.CancellationToken, + ): vscode.ProviderResult { + return debugConfiguration; } - resolveDebugConfigurationWithSubstitutedVariables(folder: vscode.WorkspaceFolder, debugConfiguration: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult { - return debugConfiguration + resolveDebugConfigurationWithSubstitutedVariables( + folder: vscode.WorkspaceFolder, + debugConfiguration: vscode.DebugConfiguration, + token?: vscode.CancellationToken, + ): vscode.ProviderResult { + return debugConfiguration; } - } diff --git a/src/extension.ts b/src/extension.ts index c74f1522..d33f3e8d 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,7 +1,7 @@ import * as vscode from "vscode"; import { getMesonTasks, getTasks, runTask, runFirstTask } from "./tasks"; import { MesonProjectExplorer } from "./treeview"; -import { TargetNode } from "./treeview/nodes/targets" +import { TargetNode } from "./treeview/nodes/targets"; import { extensionConfiguration, workspaceRelative, @@ -9,20 +9,12 @@ import { genEnvFile, useCompileCommands, clearCache, - checkMesonIsConfigured + checkMesonIsConfigured, } from "./utils"; import { DebugConfigurationProvider } from "./configprovider"; -import { - testDebugHandler, - testRunHandler, - rebuildTests -} from "./tests"; -import { - activateLinters -} from "./linters" -import { - activateFormatters -} from "./formatters" +import { testDebugHandler, testRunHandler, rebuildTests } from "./tests"; +import { activateLinters } from "./linters"; +import { activateFormatters } from "./formatters"; import { TaskQuickPickItem } from "./types"; export let extensionPath: string; @@ -48,24 +40,36 @@ export async function activate(ctx: vscode.ExtensionContext) { explorer = new MesonProjectExplorer(ctx, root, buildDir); ctx.subscriptions.push( - vscode.debug.registerDebugConfigurationProvider('cppdbg', + vscode.debug.registerDebugConfigurationProvider( + "cppdbg", new DebugConfigurationProvider(buildDir), - vscode.DebugConfigurationProviderTriggerKind.Dynamic) + vscode.DebugConfigurationProviderTriggerKind.Dynamic, + ), ); const updateHasProject = async () => { const mesonFiles = await vscode.workspace.findFiles("**/meson.build"); - vscode.commands.executeCommand("setContext", 'mesonbuild.hasProject', mesonFiles.length > 0); - } + vscode.commands.executeCommand("setContext", "mesonbuild.hasProject", mesonFiles.length > 0); + }; mesonWatcher = vscode.workspace.createFileSystemWatcher("**/meson.build", false, true, false); - mesonWatcher.onDidCreate(updateHasProject) - mesonWatcher.onDidDelete(updateHasProject) + mesonWatcher.onDidCreate(updateHasProject); + mesonWatcher.onDidDelete(updateHasProject); ctx.subscriptions.push(mesonWatcher); - await updateHasProject() - - controller = vscode.tests.createTestController('meson-test-controller', 'Meson test controller'); - controller.createRunProfile("Meson debug test", vscode.TestRunProfileKind.Debug, (request, token) => testDebugHandler(controller, request, token), true) - controller.createRunProfile("Meson run test", vscode.TestRunProfileKind.Run, (request, token) => testRunHandler(controller, request, token), true) + await updateHasProject(); + + controller = vscode.tests.createTestController("meson-test-controller", "Meson test controller"); + controller.createRunProfile( + "Meson debug test", + vscode.TestRunProfileKind.Debug, + (request, token) => testDebugHandler(controller, request, token), + true, + ); + controller.createRunProfile( + "Meson run test", + vscode.TestRunProfileKind.Run, + (request, token) => testRunHandler(controller, request, token), + true, + ); ctx.subscriptions.push(controller); let mesonTasks: Thenable | null = null; @@ -77,8 +81,8 @@ export async function activate(ctx: vscode.ExtensionContext) { }, resolveTask() { return null; - } - }) + }, + }), ); const changeHandler = async () => { @@ -103,13 +107,18 @@ export async function activate(ctx: vscode.ExtensionContext) { } else if (e.affectsConfiguration("mesonbuild")) { changeHandler(); } - }) + }), ); const compileCommandsHandler = async () => { await useCompileCommands(buildDir); }; - compileCommandsWatcher = vscode.workspace.createFileSystemWatcher(`${buildDir}/compile_commands.json`, false, false, true); + compileCommandsWatcher = vscode.workspace.createFileSystemWatcher( + `${buildDir}/compile_commands.json`, + false, + false, + true, + ); compileCommandsWatcher.onDidChange(compileCommandsHandler); compileCommandsWatcher.onDidCreate(compileCommandsHandler); ctx.subscriptions.push(compileCommandsWatcher); @@ -118,51 +127,51 @@ export async function activate(ctx: vscode.ExtensionContext) { ctx.subscriptions.push( vscode.commands.registerCommand("mesonbuild.openBuildFile", async (node: TargetNode) => { const file = node.getTarget().defined_in; - const uri = vscode.Uri.file(file) - await vscode.commands.executeCommand('vscode.open', uri); - }) + const uri = vscode.Uri.file(file); + await vscode.commands.executeCommand("vscode.open", uri); + }), ); ctx.subscriptions.push( vscode.commands.registerCommand("mesonbuild.reconfigure", async () => { runFirstTask("reconfigure"); - }) + }), ); ctx.subscriptions.push( vscode.commands.registerCommand("mesonbuild.build", async (name?: string) => { - pickAndRunTask("build", name) - }) + pickAndRunTask("build", name); + }), ); ctx.subscriptions.push( vscode.commands.registerCommand("mesonbuild.install", async () => { runFirstTask("install"); - }) + }), ); ctx.subscriptions.push( vscode.commands.registerCommand("mesonbuild.test", async (name?: string) => { pickAndRunTask("test", name); - }) + }), ); ctx.subscriptions.push( vscode.commands.registerCommand("mesonbuild.benchmark", async (name?: string) => { pickAndRunTask("benchmark", name); - }) + }), ); ctx.subscriptions.push( vscode.commands.registerCommand("mesonbuild.clean", async () => { runFirstTask("clean"); - }) + }), ); ctx.subscriptions.push( vscode.commands.registerCommand("mesonbuild.run", async () => { pickAndRunTask("run"); - }) + }), ); if (!checkMesonIsConfigured(buildDir)) { @@ -174,11 +183,11 @@ export async function activate(ctx: vscode.ExtensionContext) { always = "Always", no = "No", never = "Never", - }; + } const response = await vscode.window.showInformationMessage( "Meson project detected in this workspace but does not seems to be configured. Would you like VS Code to configure it?", - ...Object.values(Options) + ...Object.values(Options), ); switch (response) { @@ -214,13 +223,13 @@ export async function activate(ctx: vscode.ExtensionContext) { const runnableTasks = await getTasks(mode); picker.busy = false; - picker.items = runnableTasks.map(task => { + picker.items = runnableTasks.map((task) => { return { label: task.name, detail: task.detail, picked: false, task: task, - } + }; }); return new Promise((resolve, reject) => { diff --git a/src/formatters.ts b/src/formatters.ts index 137ff630..8e504d66 100644 --- a/src/formatters.ts +++ b/src/formatters.ts @@ -1,30 +1,21 @@ -import * as vscode from 'vscode'; -import { - extensionConfiguration, - getOutputChannel -} from './utils'; -import { - ToolCheckFunc, - Tool -} from './types' +import * as vscode from "vscode"; +import { extensionConfiguration, getOutputChannel } from "./utils"; +import { ToolCheckFunc, Tool } from "./types"; import * as muon from "./tools/muon"; -type FormatterFunc = ( - tool: Tool, - document: vscode.TextDocument -) => Promise +type FormatterFunc = (tool: Tool, document: vscode.TextDocument) => Promise; type FormatterDefinition = { - format: FormatterFunc, - check: ToolCheckFunc, -} + format: FormatterFunc; + check: ToolCheckFunc; +}; const formatters: Record = { muon: { format: muon.format, check: muon.check, - } -} + }, +}; async function reloadFormatters(context: vscode.ExtensionContext): Promise { let disposables: vscode.Disposable[] = []; @@ -38,16 +29,16 @@ async function reloadFormatters(context: vscode.ExtensionContext): Promise { return await props.format(tool!, document); - } - }) + }, + }); context.subscriptions.push(sub); disposables.push(sub); @@ -65,6 +56,6 @@ export async function activateFormatters(context: vscode.ExtensionContext) { } subscriptions = await reloadFormatters(context); - }) + }), ); } diff --git a/src/introspection.ts b/src/introspection.ts index b9872750..af667262 100644 --- a/src/introspection.ts +++ b/src/introspection.ts @@ -1,24 +1,16 @@ import * as path from "path"; import { exec, extensionConfiguration, parseJSONFileIfExists, getOutputChannel } from "./utils"; -import { - Targets, - Dependencies, - BuildOptions, - Tests, - ProjectInfo -} from "./types"; +import { Targets, Dependencies, BuildOptions, Tests, ProjectInfo } from "./types"; async function introspectMeson(buildDir: string, filename: string, introspectSwitch: string) { - getOutputChannel().appendLine(`Read introspection file ${filename}`) - const parsed = await parseJSONFileIfExists( - path.join(buildDir, path.join("meson-info", filename)) - ); + getOutputChannel().appendLine(`Read introspection file ${filename}`); + const parsed = await parseJSONFileIfExists(path.join(buildDir, path.join("meson-info", filename))); if (parsed) { return parsed; } const { stdout } = await exec(extensionConfiguration("mesonPath"), ["introspect", introspectSwitch], { - cwd: buildDir + cwd: buildDir, }); return JSON.parse(stdout) as T; @@ -28,7 +20,7 @@ export async function getMesonTargets(buildDir: string) { const parsed = await introspectMeson(buildDir, "intro-targets.json", "--targets"); if ((await getMesonVersion())[1] < 50) { - return parsed.map(t => { + return parsed.map((t) => { if (typeof t.filename === "string") t.filename = [t.filename]; // Old versions would directly pass a string with only 1 filename on the target return t; }); @@ -62,13 +54,6 @@ export async function getMesonVersion(): Promise<[number, number, number]> { const { stdout } = await exec(extensionConfiguration("mesonPath"), ["--version"]); const match = stdout.trim().match(MESON_VERSION_REGEX); if (match) { - return match.slice(1, 3).map(s => Number.parseInt(s)) as [ - number, - number, - number - ]; - } else - throw new Error( - "Meson version doesn't match expected output: " + stdout.trim() - ); + return match.slice(1, 3).map((s) => Number.parseInt(s)) as [number, number, number]; + } else throw new Error("Meson version doesn't match expected output: " + stdout.trim()); } diff --git a/src/linters.ts b/src/linters.ts index d074ed8d..536b94d5 100644 --- a/src/linters.ts +++ b/src/linters.ts @@ -1,35 +1,27 @@ -import * as vscode from 'vscode'; -import { - extensionConfiguration, - getOutputChannel, -} from "./utils"; -import { - ExtensionConfiguration, - LinterConfiguration, - ToolCheckFunc, - Tool -} from "./types" +import * as vscode from "vscode"; +import { extensionConfiguration, getOutputChannel } from "./utils"; +import { ExtensionConfiguration, LinterConfiguration, ToolCheckFunc, Tool } from "./types"; import * as muon from "./tools/muon"; -type LinterFunc = ( - tool: Tool, - sourceRoot: string, - document: vscode.TextDocument -) => Promise +type LinterFunc = (tool: Tool, sourceRoot: string, document: vscode.TextDocument) => Promise; type LinterDefinition = { - lint: LinterFunc, - check: ToolCheckFunc -} + lint: LinterFunc; + check: ToolCheckFunc; +}; const linters: Record = { muon: { lint: muon.lint, check: muon.check, - } -} + }, +}; -async function reloadLinters(sourceRoot: string, context: vscode.ExtensionContext, diagnostics: vscode.DiagnosticCollection) { +async function reloadLinters( + sourceRoot: string, + context: vscode.ExtensionContext, + diagnostics: vscode.DiagnosticCollection, +) { let disposables: vscode.Disposable[] = []; if (!extensionConfiguration("linting").enabled) { @@ -48,29 +40,33 @@ async function reloadLinters(sourceRoot: string, context: vscode.ExtensionContex const props = linters[name]; const { tool, error } = await props.check(); if (error) { - getOutputChannel().appendLine(`Failed to enable linter ${name}: ${error}`) + getOutputChannel().appendLine(`Failed to enable linter ${name}: ${error}`); getOutputChannel().show(true); continue; } - const linter = async (document: vscode.TextDocument) => await props.lint(tool!, sourceRoot, document) + const linter = async (document: vscode.TextDocument) => await props.lint(tool!, sourceRoot, document); enabledLinters.push(linter); } const lintAll = (document: vscode.TextDocument) => { - if (document.languageId != 'meson') { + if (document.languageId != "meson") { return; } - Promise.all(enabledLinters.map(l => l(document))).then(values => { + Promise.all(enabledLinters.map((l) => l(document))).then((values) => { diagnostics.set(document.uri, values.flat()); - }) - } + }); + }; const subscriptions = [ - vscode.workspace.onDidChangeTextDocument(c => lintAll(c.document)), - vscode.window.onDidChangeActiveTextEditor(e => { if (e) { lintAll(e.document) } }), - ] + vscode.workspace.onDidChangeTextDocument((c) => lintAll(c.document)), + vscode.window.onDidChangeActiveTextEditor((e) => { + if (e) { + lintAll(e.document); + } + }), + ]; for (const sub of subscriptions) { context.subscriptions.push(sub); @@ -81,7 +77,7 @@ async function reloadLinters(sourceRoot: string, context: vscode.ExtensionContex } export async function activateLinters(sourceRoot: string, context: vscode.ExtensionContext) { - const diagnostics = vscode.languages.createDiagnosticCollection('meson'); + const diagnostics = vscode.languages.createDiagnosticCollection("meson"); let subscriptions: vscode.Disposable[] = await reloadLinters(sourceRoot, context, diagnostics); @@ -93,6 +89,6 @@ export async function activateLinters(sourceRoot: string, context: vscode.Extens diagnostics.clear(); subscriptions = await reloadLinters(sourceRoot, context, diagnostics); - }) + }), ); } diff --git a/src/tasks.ts b/src/tasks.ts index e15526c3..2dcf8209 100644 --- a/src/tasks.ts +++ b/src/tasks.ts @@ -1,9 +1,5 @@ import * as vscode from "vscode"; -import { - getMesonTargets, - getMesonTests, - getMesonBenchmarks -} from "./introspection"; +import { getMesonTargets, getMesonTests, getMesonBenchmarks } from "./introspection"; import { extensionConfiguration, getOutputChannel, getTargetName, getEnvDict } from "./utils"; import { Test, Target } from "./types"; import { checkMesonIsConfigured } from "./utils"; @@ -27,11 +23,11 @@ function createTestTask(t: Test, buildDir: string, isBenchmark: boolean) { `Test ${name}`, "Meson", new vscode.ProcessExecution(extensionConfiguration("mesonPath"), args, { - cwd: buildDir - }) + cwd: buildDir, + }), ); testTask.group = vscode.TaskGroup.Test; - testTask.detail = `Timeout: ${t.timeout}s, ${!isBenchmark && t.is_parallel ? "run in parallel" : "run serially"}` + testTask.detail = `Timeout: ${t.timeout}s, ${!isBenchmark && t.is_parallel ? "run in parallel" : "run serially"}`; return testTask; } @@ -42,14 +38,14 @@ function createRunTask(t: Target, targetName: string) { type: "meson", target: targetName, filename: t.filename[0], - mode: "run" + mode: "run", }, `Run ${targetDisplayName}`, "Meson", new vscode.ProcessExecution(t.filename[0], { cwd: vscode.workspace.rootPath, env: getEnvDict(), - }) + }), ); runTask.group = vscode.TaskGroup.Test; return runTask; @@ -58,15 +54,14 @@ function createRunTask(t: Target, targetName: string) { function createReconfigureTask(buildDir: string) { const configureOpts = extensionConfiguration("configureOptions"); const setupOpts = extensionConfiguration("setupOptions"); - const reconfigureOpts = checkMesonIsConfigured(buildDir) ? ["--reconfigure"] : [] - const args = ["setup", ...reconfigureOpts, ...configureOpts, ...setupOpts, buildDir] + const reconfigureOpts = checkMesonIsConfigured(buildDir) ? ["--reconfigure"] : []; + const args = ["setup", ...reconfigureOpts, ...configureOpts, ...setupOpts, buildDir]; return new vscode.Task( { type: "meson", mode: "reconfigure" }, "Reconfigure", "Meson", // Note "setup --reconfigure" needs to be run from the root. - new vscode.ProcessExecution(extensionConfiguration("mesonPath"), args, - { cwd: vscode.workspace.rootPath }) + new vscode.ProcessExecution(extensionConfiguration("mesonPath"), args, { cwd: vscode.workspace.rootPath }), ); } @@ -77,32 +72,40 @@ export async function getMesonTasks(buildDir: string) { "Build all targets", "Meson", new vscode.ProcessExecution(extensionConfiguration("mesonPath"), ["compile", "-C", buildDir]), - "$meson-gcc" + "$meson-gcc", ); const defaultTestTask = new vscode.Task( { type: "meson", mode: "test" }, "Run all tests", "Meson", - new vscode.ProcessExecution(extensionConfiguration("mesonPath"), ["test", ...extensionConfiguration("testOptions")], { cwd: buildDir }) + new vscode.ProcessExecution( + extensionConfiguration("mesonPath"), + ["test", ...extensionConfiguration("testOptions")], + { cwd: buildDir }, + ), ); const defaultBenchmarkTask = new vscode.Task( { type: "meson", mode: "benchmark" }, "Run all benchmarks", "Meson", - new vscode.ProcessExecution(extensionConfiguration("mesonPath"), ["test", "--benchmark", ...extensionConfiguration("benchmarkOptions")], { cwd: buildDir }) + new vscode.ProcessExecution( + extensionConfiguration("mesonPath"), + ["test", "--benchmark", ...extensionConfiguration("benchmarkOptions")], + { cwd: buildDir }, + ), ); const defaultReconfigureTask = createReconfigureTask(buildDir); const defaultInstallTask = new vscode.Task( { type: "meson", mode: "install" }, "Run install", "Meson", - new vscode.ProcessExecution(extensionConfiguration("mesonPath"), ["install"], { cwd: buildDir }) + new vscode.ProcessExecution(extensionConfiguration("mesonPath"), ["install"], { cwd: buildDir }), ); const defaultCleanTask = new vscode.Task( { type: "meson", mode: "clean" }, "Clean", "Meson", - new vscode.ProcessExecution(extensionConfiguration("mesonPath"), ["compile", "--clean"], { cwd: buildDir }) + new vscode.ProcessExecution(extensionConfiguration("mesonPath"), ["compile", "--clean"], { cwd: buildDir }), ); defaultBuildTask.group = vscode.TaskGroup.Build; defaultTestTask.group = vscode.TaskGroup.Test; @@ -115,7 +118,7 @@ export async function getMesonTasks(buildDir: string) { defaultBenchmarkTask, defaultReconfigureTask, defaultCleanTask, - defaultInstallTask + defaultInstallTask, ]; // Remaining tasks needs a valid configuration @@ -126,38 +129,40 @@ export async function getMesonTasks(buildDir: string) { const [targets, tests, benchmarks] = await Promise.all([ getMesonTargets(buildDir), getMesonTests(buildDir), - getMesonBenchmarks(buildDir) + getMesonBenchmarks(buildDir), ]); tasks.push( - ...(await Promise.all( - targets.map(async t => { - const targetName = await getTargetName(t); - const def: MesonTaskDefinition = { - type: "meson", - target: targetName, - mode: "build" - }; - const buildTask = new vscode.Task( - def, - `Build ${targetName}`, - "Meson", - new vscode.ProcessExecution(extensionConfiguration("mesonPath"), ["compile", targetName], { - cwd: buildDir - }), - "$meson-gcc" - ); - buildTask.group = vscode.TaskGroup.Build; - // FIXME: We should only include executable installed in bindir, - // but install_dir is missing from intro data. - if (t.type == "executable" && t.installed) { - return [buildTask, createRunTask(t, targetName)]; - } - return buildTask; - }) - )).flat(1), - ...tests.map(t => createTestTask(t, buildDir, false)), - ...benchmarks.map(b => createTestTask(b, buildDir, true)) + ...( + await Promise.all( + targets.map(async (t) => { + const targetName = await getTargetName(t); + const def: MesonTaskDefinition = { + type: "meson", + target: targetName, + mode: "build", + }; + const buildTask = new vscode.Task( + def, + `Build ${targetName}`, + "Meson", + new vscode.ProcessExecution(extensionConfiguration("mesonPath"), ["compile", targetName], { + cwd: buildDir, + }), + "$meson-gcc", + ); + buildTask.group = vscode.TaskGroup.Build; + // FIXME: We should only include executable installed in bindir, + // but install_dir is missing from intro data. + if (t.type == "executable" && t.installed) { + return [buildTask, createRunTask(t, targetName)]; + } + return buildTask; + }), + ) + ).flat(1), + ...tests.map((t) => createTestTask(t, buildDir, false)), + ...benchmarks.map((b) => createTestTask(b, buildDir, true)), ); return tasks; } catch (e: any) { @@ -168,9 +173,7 @@ export async function getMesonTasks(buildDir: string) { getOutputChannel().appendLine(e.stderr); } - vscode.window.showErrorMessage( - "Could not fetch targets. See Meson Build output tab for more info." - ); + vscode.window.showErrorMessage("Could not fetch targets. See Meson Build output tab for more info."); return []; } @@ -178,9 +181,7 @@ export async function getMesonTasks(buildDir: string) { export async function getTask(mode: string, name?: string) { const tasks = await vscode.tasks.fetchTasks({ type: "meson" }); - const filtered = tasks.filter( - (t) => t.definition["mode"] == mode && (!name || t.definition["target"] == name) - ); + const filtered = tasks.filter((t) => t.definition["mode"] == mode && (!name || t.definition["target"] == name)); if (filtered.length === 0) { throw new Error(`Cannot find ${mode} target ${name}.`); } @@ -190,9 +191,7 @@ export async function getTask(mode: string, name?: string) { export async function getTasks(mode: string) { const tasks = await vscode.tasks.fetchTasks({ type: "meson" }); - return tasks.filter( - (t) => t.definition["mode"] === mode - ); + return tasks.filter((t) => t.definition["mode"] === mode); } export async function runTask(task: vscode.Task) { diff --git a/src/tests.ts b/src/tests.ts index 3f3e6e9b..c32d7327 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,48 +1,48 @@ import * as vscode from "vscode"; -import { - ExecResult, - exec, - extensionConfiguration, - workspaceRelative, -} from "./utils"; -import { - Tests -} from "./types" -import { - getMesonTests, - getMesonTargets -} from "./introspection" +import { ExecResult, exec, extensionConfiguration, workspaceRelative } from "./utils"; +import { Tests } from "./types"; +import { getMesonTests, getMesonTargets } from "./introspection"; export async function rebuildTests(controller: vscode.TestController) { - let tests = await getMesonTests(workspaceRelative(extensionConfiguration("buildFolder"))) + let tests = await getMesonTests(workspaceRelative(extensionConfiguration("buildFolder"))); - controller.items.forEach(item => { - if (!tests.some(test => item.id == test.name)) { + controller.items.forEach((item) => { + if (!tests.some((test) => item.id == test.name)) { controller.items.delete(item.id); } }); for (let testDescr of tests) { - let testItem = controller.createTestItem(testDescr.name, testDescr.name) - controller.items.add(testItem) + let testItem = controller.createTestItem(testDescr.name, testDescr.name); + controller.items.add(testItem); } } -export async function testRunHandler(controller: vscode.TestController, request: vscode.TestRunRequest, token: vscode.CancellationToken) { +export async function testRunHandler( + controller: vscode.TestController, + request: vscode.TestRunRequest, + token: vscode.CancellationToken, +) { const run = controller.createTestRun(request, undefined, false); const queue: vscode.TestItem[] = []; if (request.include) { - request.include.forEach(test => queue.push(test)); + request.include.forEach((test) => queue.push(test)); } else { - controller.items.forEach(test => queue.push(test)); + controller.items.forEach((test) => queue.push(test)); } for (let test of queue) { run.started(test); let starttime = Date.now(); try { - await exec(extensionConfiguration("mesonPath"), ['test', '-C', workspaceRelative(extensionConfiguration("buildFolder")), '--print-errorlog', test.id]); + await exec(extensionConfiguration("mesonPath"), [ + "test", + "-C", + workspaceRelative(extensionConfiguration("buildFolder")), + "--print-errorlog", + test.id, + ]); let duration = Date.now() - starttime; run.passed(test, duration); } catch (e) { @@ -62,14 +62,18 @@ export async function testRunHandler(controller: vscode.TestController, request: run.end(); } -export async function testDebugHandler(controller: vscode.TestController, request: vscode.TestRunRequest, token: vscode.CancellationToken) { +export async function testDebugHandler( + controller: vscode.TestController, + request: vscode.TestRunRequest, + token: vscode.CancellationToken, +) { const run = controller.createTestRun(request, undefined, false); const queue: vscode.TestItem[] = []; if (request.include) { - request.include.forEach(test => queue.push(test)); + request.include.forEach((test) => queue.push(test)); } else { - controller.items.forEach(test => queue.push(test)); + controller.items.forEach((test) => queue.push(test)); } const tests: Tests = await getMesonTests(workspaceRelative(extensionConfiguration("buildFolder"))); @@ -77,11 +81,13 @@ export async function testDebugHandler(controller: vscode.TestController, reques /* while meson has the --gdb arg to test, but IMO we should go the actual debugger route. * We still want stuff to be built though... Without going through weird dances */ - const relevantTests = tests.filter(test => queue.some(candidate => candidate.id == test.name)); - const requiredTargets = targets.filter(target => relevantTests.some(test => test.depends.some(dep => dep == target.id))); + const relevantTests = tests.filter((test) => queue.some((candidate) => candidate.id == test.name)); + const requiredTargets = targets.filter((target) => + relevantTests.some((test) => test.depends.some((dep) => dep == target.id)), + ); - var args = ['compile', '-C', workspaceRelative(extensionConfiguration("buildFolder"))] - requiredTargets.forEach(target => { + var args = ["compile", "-C", workspaceRelative(extensionConfiguration("buildFolder"))]; + requiredTargets.forEach((target) => { args.push(target.name); }); @@ -93,12 +99,12 @@ export async function testDebugHandler(controller: vscode.TestController, reques return; } - let configDebugOptions = extensionConfiguration("debugOptions") + let configDebugOptions = extensionConfiguration("debugOptions"); /* We already figured out which tests we want to run. * We don't use the actual test either way, as we don't get the result here... */ for (let test of relevantTests) { - let args = [...test.cmd] + let args = [...test.cmd]; args.shift(); let debugConfiguration = { diff --git a/src/tools/muon.ts b/src/tools/muon.ts index d6124bd2..1cb45b9a 100644 --- a/src/tools/muon.ts +++ b/src/tools/muon.ts @@ -1,29 +1,17 @@ -import * as vscode from 'vscode'; -import { - ExecResult, - exec, - execFeed, - extensionConfiguration, - getOutputChannel -} from "../utils" -import { - Tool -} from "../types" - -export async function lint( - muon: Tool, - root: string, - document: vscode.TextDocument -): Promise { +import * as vscode from "vscode"; +import { ExecResult, exec, execFeed, extensionConfiguration, getOutputChannel } from "../utils"; +import { Tool } from "../types"; + +export async function lint(muon: Tool, root: string, document: vscode.TextDocument): Promise { const { stderr } = await execFeed( muon.path, ["analyze", "-l", "-O", document.uri.fsPath], { cwd: root }, - document.getText() - ) + document.getText(), + ); let diagnostics: vscode.Diagnostic[] = []; - stderr.split("\n").forEach(line => { + stderr.split("\n").forEach((line) => { const parts = line.split(":"); if (parts.length < 4) { return; @@ -54,27 +42,24 @@ export async function lint( return diagnostics; } -export async function format( - muon: Tool, - document: vscode.TextDocument -): Promise { +export async function format(muon: Tool, document: vscode.TextDocument): Promise { const originalDocumentText = document.getText(); - let args = ["fmt"] + let args = ["fmt"]; if (muon.version[0] == 0 && muon.version[1] == 0) { - args = ["fmt_unstable"] + args = ["fmt_unstable"]; } - const config_path = extensionConfiguration("formatting").muonConfig + const config_path = extensionConfiguration("formatting").muonConfig; if (config_path) { - args.push("-c", config_path) + args.push("-c", config_path); } - args.push("-") + args.push("-"); const { stdout, stderr, error } = await execFeed(muon.path, args, {}, originalDocumentText); if (error) { - getOutputChannel().appendLine(`Failed to format document with muon: ${stderr}`) + getOutputChannel().appendLine(`Failed to format document with muon: ${stderr}`); getOutputChannel().show(true); return []; } @@ -87,31 +72,33 @@ export async function format( return [new vscode.TextEdit(documentRange, stdout)]; } -export async function check(): Promise<{ tool?: Tool, error?: string }> { +export async function check(): Promise<{ tool?: Tool; error?: string }> { const muon_path = extensionConfiguration("muonPath"); let stdout: string, stderr: string; try { ({ stdout, stderr } = await exec(muon_path, ["version"])); - } - catch (e) { + } catch (e) { const { error, stdout, stderr } = e as ExecResult; console.log(error); return { error: error!.message }; } - const line1 = stdout.split("\n")[0].split(" ") + const line1 = stdout.split("\n")[0].split(" "); if (line1.length !== 2) { return { error: `Invalid version string: ${line1}` }; } - const ver = line1[1].split("-")[0].split('.').map((s) => { - if (s[0] == 'v') { - s = s.slice(1) - } + const ver = line1[1] + .split("-")[0] + .split(".") + .map((s) => { + if (s[0] == "v") { + s = s.slice(1); + } - return Number.parseInt(s) - }) as [number, number, number]; + return Number.parseInt(s); + }) as [number, number, number]; return { tool: { path: muon_path, version: ver } }; } diff --git a/src/treeview/basenode.ts b/src/treeview/basenode.ts index 54e1228d..1149ab7a 100644 --- a/src/treeview/basenode.ts +++ b/src/treeview/basenode.ts @@ -3,7 +3,7 @@ import * as vscode from "vscode"; import { hash } from "../utils"; export abstract class BaseNode { - constructor(protected readonly id: string) { } + constructor(protected readonly id: string) {} getChildren(): vscode.ProviderResult { return []; diff --git a/src/treeview/index.ts b/src/treeview/index.ts index a947649e..5143b480 100644 --- a/src/treeview/index.ts +++ b/src/treeview/index.ts @@ -9,12 +9,12 @@ class MesonProjectDataProvider implements vscode.TreeDataProvider { static readonly commandName = "mesonbuild.view-refresh"; - constructor(ctx: vscode.ExtensionContext, private readonly projectDir: string, private readonly buildDir: string) { - ctx.subscriptions.push( - vscode.commands.registerCommand(MesonProjectDataProvider.commandName, () => - this.refresh() - ) - ); + constructor( + ctx: vscode.ExtensionContext, + private readonly projectDir: string, + private readonly buildDir: string, + ) { + ctx.subscriptions.push(vscode.commands.registerCommand(MesonProjectDataProvider.commandName, () => this.refresh())); } refresh() { @@ -41,7 +41,7 @@ export class MesonProjectExplorer { constructor(ctx: vscode.ExtensionContext, projectDir: string, buildDir: string) { const treeDataProvider = new MesonProjectDataProvider(ctx, projectDir, buildDir); this.viewer = vscode.window.createTreeView("meson-project", { - treeDataProvider + treeDataProvider, }); } diff --git a/src/treeview/nodes/base.ts b/src/treeview/nodes/base.ts index 0df76aa2..866c94ac 100644 --- a/src/treeview/nodes/base.ts +++ b/src/treeview/nodes/base.ts @@ -8,7 +8,11 @@ type FolderMap = Map; export abstract class BaseDirectoryNode extends BaseNode { protected subfolders: Thenable>; - constructor(id: string, protected readonly folder: string, protected readonly filepaths: T[]) { + constructor( + id: string, + protected readonly folder: string, + protected readonly filepaths: T[], + ) { super(id); const subs = this.buildFileTree(filepaths); diff --git a/src/treeview/nodes/sources.ts b/src/treeview/nodes/sources.ts index 7337994d..758f43da 100644 --- a/src/treeview/nodes/sources.ts +++ b/src/treeview/nodes/sources.ts @@ -46,14 +46,18 @@ abstract class BaseFileDirectoryNode extends BaseDirectoryNode { } export class TargetSourcesRootNode extends BaseFileDirectoryNode { - constructor(parentId: string, rootFolder: string, private readonly allFiles: string[]) { + constructor( + parentId: string, + rootFolder: string, + private readonly allFiles: string[], + ) { super(`${parentId}-sources`, rootFolder, allFiles); } override getTreeItem() { const item = super.getTreeItem() as vscode.TreeItem; - item.label = `Sources${(this.allFiles.length === 0) ? " (no files)" : ""}`; + item.label = `Sources${this.allFiles.length === 0 ? " (no files)" : ""}`; item.iconPath = extensionRelative("res/meson_32.svg"); return item; @@ -91,7 +95,10 @@ export class TargetSourceDirectoryNode extends BaseFileDirectoryNode { } export class TargetSourceFileNode extends BaseNode { - constructor(parentId: string, private readonly file: string) { + constructor( + parentId: string, + private readonly file: string, + ) { super(`${parentId}-${path.basename(file)}`); } @@ -103,7 +110,7 @@ export class TargetSourceFileNode extends BaseNode { item.command = { command: "vscode.open", title: "Open file", - arguments: [vscode.Uri.file(this.file)] + arguments: [vscode.Uri.file(this.file)], }; // No children currently, so don't display toggle. diff --git a/src/treeview/nodes/targets.ts b/src/treeview/nodes/targets.ts index c115f1d2..37c87ae4 100644 --- a/src/treeview/nodes/targets.ts +++ b/src/treeview/nodes/targets.ts @@ -30,7 +30,7 @@ export class TargetDirectoryNode extends BaseDirectoryNode { return Array.from((await this.subfolders).entries()) .map(([folder, targets]) => { if (folder === ".") { - return targets.map(tgt => new TargetNode(this.id, tgt)); + return targets.map((tgt) => new TargetNode(this.id, tgt)); } else { return new TargetDirectoryNode(this.id, folder, targets); } @@ -73,7 +73,10 @@ export class TargetDirectoryNode extends BaseDirectoryNode { } export class TargetNode extends BaseNode { - constructor(parentId: string, private readonly target: Target) { + constructor( + parentId: string, + private readonly target: Target, + ) { super(`${parentId}-${target.id}`); } @@ -84,8 +87,7 @@ export class TargetNode extends BaseNode { override getChildren() { if (!this.target.target_sources) { return []; - } - else { + } else { const sources = new Array(); const generated_sources = new Array(); for (const s of this.target.target_sources) { @@ -94,7 +96,9 @@ export class TargetNode extends BaseNode { } const sourceNode = new TargetSourcesRootNode(this.id, path.dirname(this.target.defined_in), sources); - return (generated_sources.length === 0) ? [sourceNode] : [sourceNode, new TargetGeneratedSourcesRootNode(this.id, generated_sources)]; + return generated_sources.length === 0 + ? [sourceNode] + : [sourceNode, new TargetGeneratedSourcesRootNode(this.id, generated_sources)]; } } @@ -112,7 +116,7 @@ export class TargetNode extends BaseNode { item.command = { title: `Build ${this.target.name}`, command: "mesonbuild.build", - arguments: [targetName] + arguments: [targetName], }; return item; diff --git a/src/treeview/nodes/tests.ts b/src/treeview/nodes/tests.ts index 7192a006..c6ee4bea 100644 --- a/src/treeview/nodes/tests.ts +++ b/src/treeview/nodes/tests.ts @@ -5,7 +5,11 @@ import { Test, Tests } from "../../types"; import { extensionRelative } from "../../utils"; export class TestRootNode extends BaseNode { - constructor(parentId: string, private readonly tests: Tests, private readonly isBenchmark: boolean) { + constructor( + parentId: string, + private readonly tests: Tests, + private readonly isBenchmark: boolean, + ) { super(`${parentId}-${isBenchmark ? "benchmarks" : "tests"}`); } @@ -14,7 +18,8 @@ export class TestRootNode extends BaseNode { item.label = this.isBenchmark ? "Benchmarks" : "Tests"; item.iconPath = extensionRelative("res/meson_32.svg"); - item.collapsibleState = (this.tests.length === 0) ? vscode.TreeItemCollapsibleState.None : vscode.TreeItemCollapsibleState.Collapsed; + item.collapsibleState = + this.tests.length === 0 ? vscode.TreeItemCollapsibleState.None : vscode.TreeItemCollapsibleState.Collapsed; return item; } @@ -25,13 +30,17 @@ export class TestRootNode extends BaseNode { } class TestNode extends BaseNode { - constructor(parentId: string, private readonly test: Test, private readonly isBenchmark: boolean) { + constructor( + parentId: string, + private readonly test: Test, + private readonly isBenchmark: boolean, + ) { super(`${parentId}-${test.suite[0]}-${test.name}`); } override getTreeItem() { const item = super.getTreeItem() as vscode.TreeItem; - const project = this.test.suite[0].split(":")[0] + const project = this.test.suite[0].split(":")[0]; const name = `${project}:${this.test.name}`; item.label = this.test.name; @@ -39,7 +48,7 @@ class TestNode extends BaseNode { item.command = { title: `Run ${this.isBenchmark ? "benchmark" : "test"}`, command: `mesonbuild.${this.isBenchmark ? "benchmark" : "test"}`, - arguments: [name] + arguments: [name], }; // No children currently, so don't display toggle. diff --git a/src/treeview/nodes/toplevel.ts b/src/treeview/nodes/toplevel.ts index ec282609..4290b0b2 100644 --- a/src/treeview/nodes/toplevel.ts +++ b/src/treeview/nodes/toplevel.ts @@ -11,7 +11,7 @@ export class ProjectNode extends BaseNode { constructor( private readonly project: ProjectInfo, projectDir: string, - private readonly buildDir: string + private readonly buildDir: string, ) { // Unique id for the root node of this (root directory, project, build dir). // All other nodes hang off this id so they are unique. @@ -22,8 +22,7 @@ export class ProjectNode extends BaseNode { const item = super.getTreeItem() as vscode.TreeItem; item.label = `${this.project.descriptive_name}`; - if (this.project.version !== "undefined") - item.label += ` (${this.project.version})`; + if (this.project.version !== "undefined") item.label += ` (${this.project.version})`; item.iconPath = extensionRelative("res/meson_32.svg"); item.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; @@ -34,26 +33,29 @@ export class ProjectNode extends BaseNode { const targets = await getMesonTargets(this.buildDir); let children: BaseNode[] = [ - new TargetDirectoryNode(`${this.id}-targets`, + new TargetDirectoryNode( + `${this.id}-targets`, ".", - targets.filter((target) => !target.subproject) - ) + targets.filter((target) => !target.subproject), + ), ]; const all_tests = await getMesonTests(this.buildDir); - const tests = all_tests.filter(t => t.suite[0].split(":")[0] === this.project.descriptive_name); + const tests = all_tests.filter((t) => t.suite[0].split(":")[0] === this.project.descriptive_name); if (tests.length > 0) { children.push(new TestRootNode(this.id, tests, false)); } const all_benchmarks = await getMesonBenchmarks(this.buildDir); - const benchmarks = all_benchmarks.filter(t => t.suite[0].split(":")[0] === this.project.descriptive_name); + const benchmarks = all_benchmarks.filter((t) => t.suite[0].split(":")[0] === this.project.descriptive_name); if (benchmarks.length > 0) { children.push(new TestRootNode(this.id, benchmarks, true)); } if (this.project.subprojects.length > 0) { - children.push(new SubprojectsRootNode(this.id, this.project.subprojects, this.buildDir, targets, all_tests, all_benchmarks)); + children.push( + new SubprojectsRootNode(this.id, this.project.subprojects, this.buildDir, targets, all_tests, all_benchmarks), + ); } return children; @@ -77,13 +79,16 @@ class SubprojectsRootNode extends BaseNode { item.label = "Subprojects"; item.iconPath = extensionRelative("res/icon-subprojects.svg"); - item.collapsibleState = (this.subprojects.length === 0) ? vscode.TreeItemCollapsibleState.None : vscode.TreeItemCollapsibleState.Collapsed; + item.collapsibleState = + this.subprojects.length === 0 ? vscode.TreeItemCollapsibleState.None : vscode.TreeItemCollapsibleState.Collapsed; return item; } override getChildren() { - return this.subprojects.map((subproject) => new SubprojectNode(this.id, subproject, this.buildDir, this.targets, this.tests, this.benchmarks)); + return this.subprojects.map( + (subproject) => new SubprojectNode(this.id, subproject, this.buildDir, this.targets, this.tests, this.benchmarks), + ); } } @@ -99,23 +104,25 @@ class SubprojectNode extends BaseNode { targets: Targets, tests: Tests, benchmarks: Tests, - - ) { - super(`${parentId}-${subproject.descriptive_name}${subproject.version !== "undefined" ? `-${subproject.version}` : ""}`); - this.targets = targets.filter(t => t.subproject === this.subproject.name); - this.tests = tests.filter(t => t.suite[0].split(":")[0] === this.subproject.name); - this.benchmarks = benchmarks.filter(t => t.suite[0].split(":")[0] === this.subproject.name); + ) { + super( + `${parentId}-${subproject.descriptive_name}${subproject.version !== "undefined" ? `-${subproject.version}` : ""}`, + ); + this.targets = targets.filter((t) => t.subproject === this.subproject.name); + this.tests = tests.filter((t) => t.suite[0].split(":")[0] === this.subproject.name); + this.benchmarks = benchmarks.filter((t) => t.suite[0].split(":")[0] === this.subproject.name); } override getTreeItem() { const item = super.getTreeItem() as vscode.TreeItem; - const has_children = this.targets.length > 0 || this.tests.length > 0 || this.benchmarks.length > 0 + const has_children = this.targets.length > 0 || this.tests.length > 0 || this.benchmarks.length > 0; item.label = `${this.subproject.descriptive_name}`; - if (this.subproject.version !== "undefined") - item.label += ` (${this.subproject.version})`; + if (this.subproject.version !== "undefined") item.label += ` (${this.subproject.version})`; item.iconPath = extensionRelative("res/icon-subproject.svg"); - item.collapsibleState = has_children ? vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None; + item.collapsibleState = has_children + ? vscode.TreeItemCollapsibleState.Collapsed + : vscode.TreeItemCollapsibleState.None; return item; } @@ -123,7 +130,7 @@ class SubprojectNode extends BaseNode { override async getChildren() { let children: BaseNode[] = []; if (this.targets.length > 0) { - children.push(new TargetDirectoryNode(`${this.id}-targets`, ".", this.targets)) + children.push(new TargetDirectoryNode(`${this.id}-targets`, ".", this.targets)); } if (this.tests.length > 0) { children.push(new TestRootNode(this.id, this.tests, false)); diff --git a/src/types.ts b/src/types.ts index 49fb8103..d6bba63a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,12 +1,12 @@ import * as vscode from "vscode"; type Dict = { [x: string]: T }; -export type Tool = { path: string, version: [number, number, number] } -export type ToolCheckFunc = () => Promise<{ tool?: Tool, error?: string }> +export type Tool = { path: string; version: [number, number, number] }; +export type ToolCheckFunc = () => Promise<{ tool?: Tool; error?: string }>; export type LinterConfiguration = { - enabled: boolean, -} + enabled: boolean; +}; export interface ExtensionConfiguration { configureOnOpen: boolean | "ask"; @@ -19,12 +19,12 @@ export interface ExtensionConfiguration { muonPath: string; linting: { enabled: boolean }; linter: { - muon: LinterConfiguration + muon: LinterConfiguration; }; formatting: { - enabled: boolean, - provider: "muon", - muonConfig: string | null, + enabled: boolean; + provider: "muon"; + muonConfig: string | null; }; debugOptions: object; } @@ -54,14 +54,7 @@ export interface OptionTypeMap { array: string[]; } -export type SectionType = - | "core" - | "backend" - | "base" - | "compiler" - | "directory" - | "user" - | "test"; +export type SectionType = "core" | "backend" | "base" | "compiler" | "directory" | "user" | "test"; export interface TargetSource { language: LanguageID; diff --git a/src/utils.ts b/src/utils.ts index 0a506ef4..473b8788 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -13,11 +13,7 @@ export interface ExecResult { error?: cp.ExecException; } -export async function exec( - command: string, - args: string[], - options: cp.ExecOptions = {} -) { +export async function exec(command: string, args: string[], options: cp.ExecOptions = {}) { return new Promise((resolve, reject) => { cp.execFile(command, args, options, (error, stdout, stderr) => { if (error) { @@ -29,13 +25,8 @@ export async function exec( }); } -export async function execFeed( - command: string, - args: string[], - options: cp.ExecOptions = {}, - stdin: string -) { - return new Promise(resolve => { +export async function execFeed(command: string, args: string[], options: cp.ExecOptions = {}, stdin: string) { + return new Promise((resolve) => { let p = cp.execFile(command, args, options, (error, stdout, stderr) => { resolve({ stdout, stderr, error: error ? error : undefined }); }); @@ -49,8 +40,7 @@ export async function parseJSONFileIfExists(path: string) { try { const data = await fs.promises.readFile(path); return JSON.parse(data.toString()) as T; - } - catch (err) { + } catch (err) { return false; } } @@ -76,7 +66,7 @@ let _layoutPromise: Promise | null = null; async function getLayout() { const buildDir = workspaceRelative(extensionConfiguration("buildFolder")); const buildOptions = await getMesonBuildOptions(buildDir); - return buildOptions.filter(o => o.name === "layout")[0].value; + return buildOptions.filter((o) => o.name === "layout")[0].value; } export function clearCache() { @@ -94,8 +84,7 @@ export async function getTargetName(target: Target) { relativePath = path.join(relativePath, target.name); const p = relativePath.split(path.sep).join(path.posix.sep); return `${p}:${target.type.replace(" ", "_")}`; - } - else { + } else { return `meson-out/${target.name}`; } } @@ -110,18 +99,14 @@ export function getConfiguration() { return vscode.workspace.getConfiguration("mesonbuild"); } -export function extensionConfiguration( - key: K -) { +export function extensionConfiguration(key: K) { return getConfiguration().get(key)!; } -export function extensionConfigurationSet< - K extends keyof ExtensionConfiguration ->( +export function extensionConfigurationSet( key: K, value: ExtensionConfiguration[K], - target = vscode.ConfigurationTarget.Global + target = vscode.ConfigurationTarget.Global, ) { return getConfiguration().update(key, value, target); } @@ -137,22 +122,29 @@ export function isThenable(x: vscode.ProviderResult): x is Thenable { let _envDict: { [key: string]: string } | undefined = undefined; export async function genEnvFile(buildDir: string) { - const envfile = path.join(buildDir, "meson-vscode.env") + const envfile = path.join(buildDir, "meson-vscode.env"); try { - await exec( - extensionConfiguration("mesonPath"), ["devenv", "-C", buildDir, "--dump", envfile, "--dump-format", "vscode"]); + await exec(extensionConfiguration("mesonPath"), [ + "devenv", + "-C", + buildDir, + "--dump", + envfile, + "--dump-format", + "vscode", + ]); } catch { // Ignore errors, Meson could be too old to support --dump-format. return; } // Load into a dict because vscode.ProcessExecution() does not support envFile. - _envDict = {} + _envDict = {}; const data = await fs.promises.readFile(envfile); for (const i of data.toString().split(/\r?\n/)) { // Poor man's i.split("=", 1), JS won't return part after first equal sign. // Value is quoted, remove first and last " char and also possible \r ending. - const index = i.indexOf('='); + const index = i.indexOf("="); const key = i.substring(0, index); const value = i.slice(index + 2, -1); _envDict[key] = value; @@ -172,7 +164,7 @@ export async function useCompileCommands(buildDir: string) { const conf = vscode.workspace.getConfiguration("C_Cpp"); conf.update("default.compileCommands", relFilePath, vscode.ConfigurationTarget.Workspace); } catch { - // Ignore, C/C++ extension might not be installed + // Ignore, C/C++ extension might not be installed } } } @@ -181,5 +173,5 @@ export async function useCompileCommands(buildDir: string) { // Note: With Meson >= 1.1.0 we can always pass --reconfigure even if it was // not already configured. export function checkMesonIsConfigured(buildDir: string) { - return fs.existsSync(path.join(buildDir, "meson-private", "coredata.dat")) + return fs.existsSync(path.join(buildDir, "meson-private", "coredata.dat")); } diff --git a/tsconfig.json b/tsconfig.json index abd6c40d..44c415dc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,9 +3,7 @@ "module": "commonjs", "target": "ES2020", "outDir": "out", - "lib": [ - "ES2020" - ], + "lib": ["ES2020"], "sourceMap": true, "rootDir": "src", "strict": true, diff --git a/yarn.lock b/yarn.lock index 32a2ff4d..1b4c8862 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,12 +12,364 @@ resolved "https://registry.npmjs.org/@types/vscode/-/vscode-1.64.0.tgz" integrity sha512-bSlAWz5WtcSL3cO9tAT/KpEH9rv5OBnm93OIIFwdCshaAiqr2bp1AUyEwW9MWeCvZBHEXc3V0fTYVdVyzDNwHA== +ansi-escapes@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-5.0.0.tgz#b6a0caf0eef0c41af190e9a749e0c00ec04bb2a6" + integrity sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA== + dependencies: + type-fest "^1.0.2" + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + +ansi-styles@^6.0.0, ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +braces@^3.0.2: + 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" + +chalk@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + +cli-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" + integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== + dependencies: + restore-cursor "^4.0.0" + +cli-truncate@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389" + integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA== + dependencies: + slice-ansi "^5.0.0" + string-width "^5.0.0" + +colorette@^2.0.20: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +commander@11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-11.0.0.tgz#43e19c25dbedc8256203538e8d7e9346877a6f67" + integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ== + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +execa@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9" + integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.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" + +get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + +husky@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" + integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== + +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + +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-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +lilconfig@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== + +lint-staged@^14.0.1: + version "14.0.1" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-14.0.1.tgz#57dfa3013a3d60762d9af5d9c83bdb51291a6232" + integrity sha512-Mw0cL6HXnHN1ag0mN/Dg4g6sr8uf8sn98w2Oc1ECtFto9tvRF7nkXGJRbx8gPlHyoR0pLyBr2lQHbWwmUHe1Sw== + dependencies: + chalk "5.3.0" + commander "11.0.0" + debug "4.3.4" + execa "7.2.0" + lilconfig "2.1.0" + listr2 "6.6.1" + micromatch "4.0.5" + pidtree "0.6.0" + string-argv "0.3.2" + yaml "2.3.1" + +listr2@6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-6.6.1.tgz#08b2329e7e8ba6298481464937099f4a2cd7f95d" + integrity sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg== + dependencies: + cli-truncate "^3.1.0" + colorette "^2.0.20" + eventemitter3 "^5.0.1" + log-update "^5.0.1" + rfdc "^1.3.0" + wrap-ansi "^8.1.0" + +log-update@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-5.0.1.tgz#9e928bf70cb183c1f0c9e91d9e6b7115d597ce09" + integrity sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw== + dependencies: + ansi-escapes "^5.0.0" + cli-cursor "^4.0.0" + slice-ansi "^5.0.0" + strip-ansi "^7.0.1" + wrap-ansi "^8.0.1" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +micromatch@4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== + dependencies: + path-key "^4.0.0" + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pidtree@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" + integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== + +prettier@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643" + integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg== + +restore-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" + integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.2, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +slice-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" + integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + dependencies: + ansi-styles "^6.0.0" + is-fullwidth-code-point "^4.0.0" + +string-argv@0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" + integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== + +string-width@^5.0.0, string-width@^5.0.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + +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" + +type-fest@^1.0.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" + integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== + typescript@^4.4.4: version "4.4.4" resolved "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz" integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== -vscode-nls@^5.0.0: - version "5.2.0" - resolved "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz" - integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng== +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +yaml@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" + integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==